From eac445c85a6059b783e9c4aa067ba133af47bb95 Mon Sep 17 00:00:00 2001 From: WinCPP Date: Sat, 3 Mar 2018 18:57:37 +0530 Subject: [PATCH] Issue #24343 Vector Ctor using Span --- .../ref/System.Numerics.Vectors.cs | 3 + .../ref/System.Numerics.Vectors.csproj | 1 + .../src/System.Numerics.Vectors.csproj | 1 + .../tests/GenericVectorTests.cs | 19 +- .../tests/GenericVectorTests.netcoreapp.cs | 233 ++++++++++++ .../tests/GenericVectorTests.netcoreapp.tt | 181 +++++++++ .../tests/GenericVectorTests.tt | 6 +- .../GenericVectorConstructorTests.cs | 353 ++++++++++++++++++ .../GenericVectorConstructorTests.tt | 120 ++++++ ....Numerics.Vectors.Performance.Tests.csproj | 22 ++ .../System.Numerics.Vectors.Tests.csproj | 14 + 11 files changed, 946 insertions(+), 7 deletions(-) create mode 100644 src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.cs create mode 100644 src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.tt create mode 100644 src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.cs create mode 100644 src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.tt diff --git a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 486ad29db961..9936f6695440 100644 --- a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -301,6 +301,9 @@ public partial struct Vector : System.IEquatable>, public Vector(T value) { throw null; } public Vector(T[] values) { throw null; } public Vector(T[] values, int index) { throw null; } +#if netcoreapp + public Vector(Span values) { throw null; } +#endif public static int Count { get { throw null; } } public T this[int index] { get { throw null; } } public static System.Numerics.Vector One { get { throw null; } } diff --git a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj index b585b3369a1e..5ac70e7e0522 100644 --- a/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj +++ b/src/System.Numerics.Vectors/ref/System.Numerics.Vectors.csproj @@ -4,6 +4,7 @@ {650277B5-9423-4ACE-BB54-2659995B21C7} true + $(DefineConstants);netcoreapp diff --git a/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj b/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj index 47a3bf9c341a..d72e3435765d 100644 --- a/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj +++ b/src/System.Numerics.Vectors/src/System.Numerics.Vectors.csproj @@ -10,6 +10,7 @@ true true netstandard1.0;portable-net45+win8+wp8+wpa81 + $(DefineConstants);netcoreapp diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/System.Numerics.Vectors/tests/GenericVectorTests.cs index e03022a21608..e06cb36be623 100644 --- a/src/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -14,7 +14,7 @@ namespace System.Numerics.Tests /// /// Vector{T} tests that use random number generation and a unified generic test structure /// - public class GenericVectorTests + public partial class GenericVectorTests { // Static constructor in top-level class\ static System.Numerics.Vector dummy; @@ -2699,11 +2699,12 @@ private static void ValidateVector(Vector vector, Action indexVali } } - internal static T[] GenerateRandomValuesForVector() where T : struct + internal static T[] GenerateRandomValuesForVector(int numValues = int.MinValue) where T : struct { int minValue = GetMinValue(); int maxValue = GetMaxValue(); - return Util.GenerateRandomValues(Vector.Count, minValue, maxValue); + numValues = numValues == int.MinValue ? Vector.Count : numValues; + return Util.GenerateRandomValues(numValues, minValue, maxValue); } internal static int GetMinValue() where T : struct @@ -2774,6 +2775,16 @@ internal static T GetValueWithAllOnesSet() where T : struct } throw new NotSupportedException(); } + + internal static T[] GetArrayOfDefaultValues(int count) + { + T[] arr = new T[count]; + for (int index = 0; index < count; ++index) + { + arr[index] = default(T); + } + return arr; + } #endregion } -} \ No newline at end of file +} diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.cs b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.cs new file mode 100644 index 000000000000..39e50e434af5 --- /dev/null +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.cs @@ -0,0 +1,233 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Xunit; +using Xunit.Sdk; + +namespace System.Numerics.Tests +{ + /// + /// Vector{T} tests that use random number generation and a unified generic test structure + /// + public partial class GenericVectorTests + { + #region Constructor Tests + + #region Tests for Span based constructor + [Fact] + public void ConstructorWithSpanByte() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanSByte() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanUInt16() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanInt16() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanUInt32() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanInt32() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanUInt64() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanInt64() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanSingle() => TestConstructorWithSpan(); + [Fact] + public void ConstructorWithSpanDouble() => TestConstructorWithSpan(); + + private void TestConstructorWithSpan() where T : struct + { + T[] values = GenerateRandomValuesForVector().ToArray(); + Span valueSpan = new Span(values); + + var vector = new Vector(valueSpan); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + + [Fact] + public void SpanBasedConstructorWithLessElements_Byte() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_SByte() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_UInt16() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Int16() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_UInt32() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Int32() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_UInt64() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Int64() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Single() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + [Fact] + public void SpanBasedConstructorWithLessElements_Double() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements()); + + private void TestSpanBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + Span valueSpan = new Span(values); + + Vector v = new Vector(valueSpan); + } + + #endregion Tests for Span based constructor + + #region Tests for Array based constructor + + [Fact] + public void ArrayBasedConstructor_Byte() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_SByte() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_UInt16() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Int16() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_UInt32() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Int32() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_UInt64() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Int64() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Single() => TestArrayBasedConstructor(); + [Fact] + public void ArrayBasedConstructor_Double() => TestArrayBasedConstructor(); + + private void TestArrayBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count).ToArray(); + Vector vector = new Vector(values); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + + [Fact] + public void ArrayIndexBasedConstructor_Byte() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_SByte() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_UInt16() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Int16() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_UInt32() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Int32() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_UInt64() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Int64() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Single() => TestArrayIndexBasedConstructor(); + [Fact] + public void ArrayIndexBasedConstructor_Double() => TestArrayIndexBasedConstructor(); + + private void TestArrayIndexBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + int offset = Vector.Count - 1; + Vector vector = new Vector(values, offset); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[offset + index], val); + }); + } + + [Fact] + public void ArrayBasedConstructorWithLessElements_Byte() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_SByte() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_UInt16() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_Int16() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_UInt32() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_Int32() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_UInt64() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_Int64() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_Single() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + [Fact] + public void ArrayBasedConstructorWithLessElements_Double() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements()); + + private void TestArrayBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + Vector v = new Vector(values); + } + + [Fact] + public void ArrayIndexBasedConstructorLessElements_Byte() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_SByte() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_UInt16() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Int16() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_UInt32() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Int32() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_UInt64() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Int64() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Single() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + [Fact] + public void ArrayIndexBasedConstructorLessElements_Double() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements()); + + private void TestArrayIndexBasedConstructorLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + Vector v = new Vector(values, Vector.Count + 1); + } + + #endregion Tests for Array based constructor + + #region Tests for constructors using unsupported types + + [Fact] + public void ConstructorWithUnsupportedTypes_Guid() => TestConstructorWithUnsupportedTypes(); + [Fact] + public void ConstructorWithUnsupportedTypes_DateTime() => TestConstructorWithUnsupportedTypes(); + [Fact] + public void ConstructorWithUnsupportedTypes_Char() => TestConstructorWithUnsupportedTypes(); + + private void TestConstructorWithUnsupportedTypes() where T : struct + { + Assert.Throws(() => + { + T[] arr = GetArrayOfDefaultValues(4); + Span span = new Span(arr); + Vector vector = new Vector(span); + }); + } + + #endregion Tests for constructors using unsupported types + + #endregion Constructor Tests + } +} diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.tt b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.tt new file mode 100644 index 000000000000..3ed408209cfd --- /dev/null +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.netcoreapp.tt @@ -0,0 +1,181 @@ +<#@ template debug="true" hostSpecific="true" #> +<#@ output extension=".cs" #> +<#@ Assembly Name="System.Core.dll" #> +<#@ Assembly Name="System.Xml.dll" #> +<#@ import namespace="System" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Runtime.InteropServices" #> +<#@ include file="..\..\Common\src\CoreLib\System\Numerics\GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Xunit; +using Xunit.Sdk; + +namespace System.Numerics.Tests +{ + /// + /// Vector{T} tests that use random number generation and a unified generic test structure + /// + public partial class GenericVectorTests + { + #region Constructor Tests + + #region Tests for Span based constructor +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ConstructorWithSpan<#=type.Name#>() => TestConstructorWithSpan<<#=type.Name#>>(); +<# + } +#> + + private void TestConstructorWithSpan() where T : struct + { + T[] values = GenerateRandomValuesForVector().ToArray(); + Span valueSpan = new Span(values); + + var vector = new Vector(valueSpan); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void SpanBasedConstructorWithLessElements_<#=type.Name#>() => Assert.Throws(() => TestSpanBasedConstructorWithLessElements<<#=type.Name#>>()); +<# + } +#> + + private void TestSpanBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + Span valueSpan = new Span(values); + + Vector v = new Vector(valueSpan); + } + + #endregion Tests for Span based constructor + + #region Tests for Array based constructor + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayBasedConstructor_<#=type.Name#>() => TestArrayBasedConstructor<<#=type.Name#>>(); +<# + } +#> + + private void TestArrayBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count).ToArray(); + Vector vector = new Vector(values); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[index], val); + }); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayIndexBasedConstructor_<#=type.Name#>() => TestArrayIndexBasedConstructor<<#=type.Name#>>(); +<# + } +#> + + private void TestArrayIndexBasedConstructor() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + int offset = Vector.Count - 1; + Vector vector = new Vector(values, offset); + ValidateVector(vector, + (index, val) => + { + Assert.Equal(values[offset + index], val); + }); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayBasedConstructorWithLessElements_<#=type.Name#>() => Assert.Throws(() => TestArrayBasedConstructorWithLessElements<<#=type.Name#>>()); +<# + } +#> + + private void TestArrayBasedConstructorWithLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count - 1).ToArray(); + Vector v = new Vector(values); + } + +<# + foreach (var type in supportedTypes) + { +#> + [Fact] + public void ArrayIndexBasedConstructorLessElements_<#=type.Name#>() => Assert.Throws(() => TestArrayIndexBasedConstructorLessElements<<#=type.Name#>>()); +<# + } +#> + + private void TestArrayIndexBasedConstructorLessElements() where T : struct + { + T[] values = GenerateRandomValuesForVector(Vector.Count * 2).ToArray(); + Vector v = new Vector(values, Vector.Count + 1); + } + + #endregion Tests for Array based constructor + + #region Tests for constructors using unsupported types + +<# + Type[] unsupportedTypes = new[] + { + typeof(Guid), typeof(DateTime), typeof(char) + }; + + + foreach (var type in unsupportedTypes) + { +#> + [Fact] + public void ConstructorWithUnsupportedTypes_<#=type.Name#>() => TestConstructorWithUnsupportedTypes<<#=type.Name#>>(); +<# + } +#> + + private void TestConstructorWithUnsupportedTypes() where T : struct + { + Assert.Throws(() => + { + T[] arr = GetArrayOfDefaultValues(4); + Span span = new Span(arr); + Vector vector = new Vector(span); + }); + } + + #endregion Tests for constructors using unsupported types + + #endregion Constructor Tests + } +} diff --git a/src/System.Numerics.Vectors/tests/GenericVectorTests.tt b/src/System.Numerics.Vectors/tests/GenericVectorTests.tt index 4790b1ac50f1..67295b70b31b 100644 --- a/src/System.Numerics.Vectors/tests/GenericVectorTests.tt +++ b/src/System.Numerics.Vectors/tests/GenericVectorTests.tt @@ -19,7 +19,7 @@ namespace System.Numerics.Tests /// /// Vector{T} tests that use random number generation and a unified generic test structure /// - public class GenericVectorTests + public partial class GenericVectorTests { // Static constructor in top-level class\ static System.Numerics.Vector dummy; @@ -116,7 +116,7 @@ namespace System.Numerics.Tests }); } -<# +<# foreach (var type in supportedTypes) { #> @@ -1869,4 +1869,4 @@ namespace System.Numerics.Tests } #endregion } -} \ No newline at end of file +} diff --git a/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.cs b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.cs new file mode 100644 index 000000000000..90a2b793cdef --- /dev/null +++ b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.cs @@ -0,0 +1,353 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Xunit; +using Xunit.Sdk; +using Microsoft.Xunit.Performance; + +namespace System.Numerics.Tests +{ + public static class Constructor + { + private static Random s_random = new Random(); + + public const int DefaultInnerIterationsCount = 100000000; + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Byte() + { + Byte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_SByte() + { + SByte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_UInt16() + { + UInt16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Int16() + { + Int16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_UInt32() + { + UInt32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Int32() + { + Int32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_UInt64() + { + UInt64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Int64() + { + Int64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Single() + { + Single[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_Double() + { + Double[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new Span(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct(spanValues); + } + } + } + + + public static void Construct(Span values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + Vector vect = new Vector(values); + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Byte() + { + Byte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_SByte() + { + SByte[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_UInt16() + { + UInt16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Int16() + { + Int16[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_UInt32() + { + UInt32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Int32() + { + Int32[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_UInt64() + { + UInt64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Int64() + { + Int64[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Single() + { + Single[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_Double() + { + Double[] arrValues = GenerateRandomValuesForVector(); + var spanValues = new ReadOnlySpan(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast(spanValues); + } + } + } + + + public static void SpanCast(ReadOnlySpan values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + ReadOnlySpan> vectors = MemoryMarshal.Cast>(values); + Vector vector = vectors[0]; + } + } + + internal static T[] GenerateRandomValuesForVector() where T : struct + { + int minValue = GetMinValue(); + int maxValue = GetMaxValue(); + return Util.GenerateRandomValues(Vector.Count, minValue, maxValue); + } + + internal static int GetMinValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MinValue; + } + var typeInfo = typeof(T).GetTypeInfo(); + var field = typeInfo.GetDeclaredField("MinValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + + internal static int GetMaxValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MaxValue; + } + var typeInfo = typeof(T).GetTypeInfo(); + var field = typeInfo.GetDeclaredField("MaxValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + + } +} diff --git a/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.tt b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.tt new file mode 100644 index 000000000000..0a2df77bea3f --- /dev/null +++ b/src/System.Numerics.Vectors/tests/Performance/Constructor/GenericVectorConstructorTests.tt @@ -0,0 +1,120 @@ +<#@ template debug="true" hostSpecific="true" #> +<#@ output extension=".cs" #> +<#@ Assembly Name="System.Core.dll" #> +<#@ Assembly Name="System.Xml.dll" #> +<#@ import namespace="System" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Runtime.InteropServices" #> +<#@ include file="..\..\..\..\Common\src\CoreLib\System\Numerics\GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Xunit; +using Xunit.Sdk; +using Microsoft.Xunit.Performance; + +namespace System.Numerics.Tests +{ + public static class Constructor + { + private static Random s_random = new Random(); + + public const int DefaultInnerIterationsCount = 100000000; + +<# + foreach (var type in supportedTypes) + { +#> + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void ConstructorBenchmark_<#=type.Name#>() + { + <#=type.Name#>[] arrValues = GenerateRandomValuesForVector<<#=type.Name#>>(); + var spanValues = new Span<<#=type.Name#>>(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + Construct<<#=type.Name#>>(spanValues); + } + } + } + +<# + } +#> + + public static void Construct(Span values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + Vector vect = new Vector(values); + } + } + +<# + foreach (var type in supportedTypes) + { +#> + [Benchmark(InnerIterationCount = DefaultInnerIterationsCount)] + public static void SpanCastBenchmark_<#=type.Name#>() + { + <#=type.Name#>[] arrValues = GenerateRandomValuesForVector<<#=type.Name#>>(); + var spanValues = new ReadOnlySpan<<#=type.Name#>>(arrValues); + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + SpanCast<<#=type.Name#>>(spanValues); + } + } + } + +<# + } +#> + + public static void SpanCast(ReadOnlySpan values) where T : struct + { + for (var iteration = 0; iteration < Benchmark.InnerIterationCount; iteration++) + { + ReadOnlySpan> vectors = MemoryMarshal.Cast>(values); + Vector vector = vectors[0]; + } + } + + internal static T[] GenerateRandomValuesForVector() where T : struct + { + int minValue = GetMinValue(); + int maxValue = GetMaxValue(); + return Util.GenerateRandomValues(Vector.Count, minValue, maxValue); + } + + internal static int GetMinValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MinValue; + } + var typeInfo = typeof(T).GetTypeInfo(); + var field = typeInfo.GetDeclaredField("MinValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + + internal static int GetMaxValue() where T : struct + { + if (typeof(T) == typeof(Int64) || typeof(T) == typeof(Single) || typeof(T) == typeof(Double) || typeof(T) == typeof(UInt32) || typeof(T) == typeof(UInt64)) + { + return int.MaxValue; + } + var typeInfo = typeof(T).GetTypeInfo(); + var field = typeInfo.GetDeclaredField("MaxValue"); + var value = field.GetValue(null); + return (int)(dynamic)value; + } + + } +} diff --git a/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj b/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj index 842a2b5a1cd5..318d8f0e627a 100644 --- a/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj +++ b/src/System.Numerics.Vectors/tests/Performance/System.Numerics.Vectors.Performance.Tests.csproj @@ -63,7 +63,29 @@ + + TextTemplatingFileGenerator + GenericVectorConstructorTests.cs + + + + + + + Util.cs + + + True + True + GenericVectorConstructorTests.tt + + + + + GenerationConfig.ttinclude + + \ No newline at end of file diff --git a/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj b/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj index fc5d885a9281..42cbe76a3c8a 100644 --- a/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj +++ b/src/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj @@ -35,6 +35,13 @@ System\MathF.netstandard.cs + + + True + True + GenericVectorTests.netcoreapp.tt + + ConstantHelper.tt @@ -50,7 +57,14 @@ + + + + TextTemplatingFileGenerator + GenericVectorTests.netcoreapp.cs + + \ No newline at end of file