diff --git a/src/benchmarks/micro/MicroBenchmarks.csproj b/src/benchmarks/micro/MicroBenchmarks.csproj
index 3d9e9fd4286..867737a3b72 100644
--- a/src/benchmarks/micro/MicroBenchmarks.csproj
+++ b/src/benchmarks/micro/MicroBenchmarks.csproj
@@ -88,6 +88,10 @@
+
+
+
+
@@ -212,9 +216,10 @@
-
-
-
+
+
+
+
diff --git a/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_BinaryIntegerTensorPrimitives.cs b/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_BinaryIntegerTensorPrimitives.cs
new file mode 100644
index 00000000000..88aa8df5c99
--- /dev/null
+++ b/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_BinaryIntegerTensorPrimitives.cs
@@ -0,0 +1,46 @@
+// 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 BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Extensions;
+using MicroBenchmarks;
+
+namespace System.Numerics.Tensors.Tests
+{
+ [BenchmarkCategory(Categories.Libraries, Categories.SIMD, Categories.JIT)]
+ [GenericTypeArguments(typeof(int))]
+ public class Perf_BinaryIntegerTensorPrimitives
+ where T : unmanaged, IBinaryInteger
+ {
+ [Params(128, 6 * 512 + 7)]
+ public int BufferLength;
+
+ private T[] _source1;
+ private T[] _destination;
+
+ [GlobalSetup]
+ public void Init()
+ {
+ _source1 = ValuesGenerator.Array(BufferLength, seed: 42);
+ _destination = new T[BufferLength];
+ }
+
+ #region Unary Operations
+ [Benchmark]
+ public void LeadingZeroCount() => TensorPrimitives.LeadingZeroCount(_source1, _destination);
+
+ [Benchmark]
+ public void OnesComplement() => TensorPrimitives.OnesComplement(_source1, _destination);
+
+ [Benchmark]
+ public void PopCount() => TensorPrimitives.PopCount(_source1, _destination);
+
+ [Benchmark]
+ public void ShiftLeft() => TensorPrimitives.ShiftLeft(_source1, shiftAmount: 3, _destination);
+
+ [Benchmark]
+ public void TrailingZeroCount() => TensorPrimitives.TrailingZeroCount(_source1, _destination);
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_FloatingPointTensorPrimitives.cs b/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_FloatingPointTensorPrimitives.cs
new file mode 100644
index 00000000000..63212e36d44
--- /dev/null
+++ b/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_FloatingPointTensorPrimitives.cs
@@ -0,0 +1,105 @@
+// 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 BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Extensions;
+using MicroBenchmarks;
+using System.Linq;
+
+namespace System.Numerics.Tensors.Tests
+{
+ [BenchmarkCategory(Categories.Libraries, Categories.SIMD, Categories.JIT)]
+ [GenericTypeArguments(typeof(float))]
+ [GenericTypeArguments(typeof(double))]
+ public class Perf_FloatingPointTensorPrimitives
+ where T : unmanaged, IFloatingPointIeee754
+ {
+ [Params(128, 6 * 512 + 7)]
+ public int BufferLength;
+
+ private T[] _source1;
+ private T[] _source2;
+ private T[] _source3;
+ private T _scalar1;
+ private T[] _ones;
+ private T[] _destination;
+
+ [GlobalSetup]
+ public void Init()
+ {
+ _source1 = ValuesGenerator.Array(BufferLength, seed: 42);
+ _source2 = ValuesGenerator.Array(BufferLength, seed: 43);
+ _source3 = ValuesGenerator.Array(BufferLength, seed: 44);
+ _scalar1 = ValuesGenerator.Value(seed: 45);
+ _ones = Enumerable.Repeat(T.One, BufferLength).ToArray();
+ _destination = new T[BufferLength];
+ }
+
+ #region Unary Operations
+ [Benchmark]
+ public void AtanPi() => TensorPrimitives.AtanPi(_source1, _destination);
+
+ [Benchmark]
+ public void Exp() => TensorPrimitives.Exp(_source1, _destination);
+
+ [Benchmark]
+ public void Log() => TensorPrimitives.Log(_source1, _destination);
+
+ [Benchmark]
+ public void Round() => TensorPrimitives.Round(_source1, _destination);
+
+ [Benchmark]
+ public void Sin() => TensorPrimitives.Sin(_source1, _destination);
+
+ [Benchmark]
+ public void Sinh() => TensorPrimitives.Sinh(_source1, _destination);
+
+ [Benchmark]
+ public void Sigmoid() => TensorPrimitives.Sigmoid(_source1, _destination);
+
+ [Benchmark]
+ public void Sqrt() => TensorPrimitives.Sqrt(_source1, _destination);
+
+ [Benchmark]
+ public void Truncate() => TensorPrimitives.Truncate(_source1, _destination);
+ #endregion
+
+ #region Binary/Ternary Operations
+ [Benchmark]
+ public void FusedMultiplyAdd_Vectors() => TensorPrimitives.FusedMultiplyAdd(_source1, _source2, _source3, _destination);
+
+ [Benchmark]
+ public void FusedMultiplyAdd_ScalarAddend() => TensorPrimitives.FusedMultiplyAdd(_source1, _scalar1, _source2, _destination);
+
+ [Benchmark]
+ public void FusedMultiplyAdd_ScalarMultiplier() => TensorPrimitives.FusedMultiplyAdd(_source1, _source2, _scalar1, _destination);
+
+ [Benchmark]
+ public void Ieee754Remainder_Vector() => TensorPrimitives.Ieee754Remainder(_source1, _source2, _destination);
+
+ [Benchmark]
+ public void Ieee754Remainder_ScalarDividend() => TensorPrimitives.Ieee754Remainder(_scalar1, _source1, _destination);
+
+ [Benchmark]
+ public void Ieee754Remainder_ScalarDivisor() => TensorPrimitives.Ieee754Remainder(_source1, _scalar1, _destination);
+
+ [Benchmark]
+ public void Pow_Vectors() => TensorPrimitives.Pow(_source1, _ones, _destination);
+
+ [Benchmark]
+ public void Pow_ScalarBase() => TensorPrimitives.Pow(_scalar1, _ones, _destination);
+
+ [Benchmark]
+ public void Pow_ScalarExponent() => TensorPrimitives.Pow(_source1, T.One, _destination);
+ #endregion
+
+ #region Reducers
+ [Benchmark]
+ public T CosineSimilarity() => TensorPrimitives.CosineSimilarity(_source1, _source2);
+
+ [Benchmark]
+ public T Distance() => TensorPrimitives.Distance(_source1, _source2);
+ #endregion
+ }
+}
diff --git a/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_NumberTensorPrimitives.cs b/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_NumberTensorPrimitives.cs
new file mode 100644
index 00000000000..a3adab1b054
--- /dev/null
+++ b/src/benchmarks/micro/libraries/System.Numerics.Tensors/Perf_NumberTensorPrimitives.cs
@@ -0,0 +1,103 @@
+// 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 BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Extensions;
+using MicroBenchmarks;
+using System.Linq;
+
+namespace System.Numerics.Tensors.Tests
+{
+ [BenchmarkCategory(Categories.Libraries, Categories.SIMD, Categories.JIT)]
+ [GenericTypeArguments(typeof(int))]
+ [GenericTypeArguments(typeof(float))]
+ [GenericTypeArguments(typeof(double))]
+ public class Perf_NumberTensorPrimitives
+ where T : INumber, IBitwiseOperators
+ {
+ [Params(128, 6 * 512 + 7)]
+ public int BufferLength;
+
+ private T[] _source1;
+ private T[] _source2;
+ private T[] _source3;
+ private T _scalar1;
+ private T[] _ones;
+ private T[] _destination;
+
+ [GlobalSetup]
+ public void Init()
+ {
+ _source1 = ValuesGenerator.Array(BufferLength, seed: 42);
+ _source2 = ValuesGenerator.Array(BufferLength, seed: 43);
+ _source3 = ValuesGenerator.Array(BufferLength, seed: 44);
+ _scalar1 = ValuesGenerator.Value(seed: 45);
+ _ones = Enumerable.Repeat(T.One, BufferLength).ToArray();
+ _destination = new T[BufferLength];
+ }
+
+ #region Unary Operations
+ [Benchmark]
+ public void Abs() => TensorPrimitives.Abs(_source1, _destination);
+
+ [Benchmark]
+ public void Negate() => TensorPrimitives.Abs(_source1, _destination);
+ #endregion
+
+ #region Binary/Ternary Operations
+ [Benchmark]
+ public void Add_Vector() => TensorPrimitives.Add(_source1, _source2, _destination);
+
+ [Benchmark]
+ public void Add_Scalar() => TensorPrimitives.Add(_source1, _scalar1, _destination);
+
+ [Benchmark]
+ public void AddMultiply_Vectors() => TensorPrimitives.AddMultiply(_source1, _source2, _source3, _destination);
+
+ [Benchmark]
+ public void AddMultiply_ScalarAddend() => TensorPrimitives.AddMultiply(_source1, _scalar1, _source2, _destination);
+
+ [Benchmark]
+ public void AddMultiply_ScalarMultiplier() => TensorPrimitives.AddMultiply(_source1, _source2, _scalar1, _destination);
+
+ [Benchmark]
+ public void BitwiseAnd_Vector() => TensorPrimitives.BitwiseAnd(_source1, _source2, _destination);
+
+ [Benchmark]
+ public void BitwiseAnd_Scalar() => TensorPrimitives.BitwiseAnd(_source1, _scalar1, _destination);
+
+ [Benchmark]
+ public void Divide_Vector() => TensorPrimitives.Divide(_source1, _ones, _destination);
+
+ [Benchmark]
+ public void Divide_Scalar() => TensorPrimitives.Divide(_source1, T.One, _destination);
+
+ [Benchmark]
+ public void Max_Vector() => TensorPrimitives.Max(_source1, _source2, _destination);
+
+ [Benchmark]
+ public void Max_Scalar() => TensorPrimitives.Max(_source1, _scalar1, _destination);
+
+ [Benchmark]
+ public void MaxMagnitude_Vector() => TensorPrimitives.MaxMagnitude(_source1, _source2, _destination);
+
+ [Benchmark]
+ public void MaxMagnitude_Scalar() => TensorPrimitives.MaxMagnitude(_source1, _scalar1, _destination);
+ #endregion
+
+ #region Reducers
+ [Benchmark]
+ public T Max() => TensorPrimitives.Max(_source1);
+
+ [Benchmark]
+ public T SumOfMagnitudes() => TensorPrimitives.SumOfMagnitudes(_ones);
+
+ [Benchmark]
+ public T SumOfSquares() => TensorPrimitives.SumOfSquares(_ones);
+
+ [Benchmark]
+ public int IndexOfMax() => TensorPrimitives.IndexOfMax(_source1);
+ #endregion
+ }
+}
diff --git a/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs b/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs
index fa36e3c17a1..1b0bc42c87e 100644
--- a/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs
+++ b/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs
@@ -67,11 +67,11 @@ public static T[] ArrayOfUniqueValues(int count)
/// For byte and sbyte values are built from Random.NextBytes, for other types GenerateValue is used
/// to generate a random value in the appropriate range
///
- public static T[] Array(int count)
+ public static T[] Array(int count, int? seed = null)
{
var result = new T[count];
- var random = new Random(Seed);
+ var random = new Random(seed ?? Seed);
if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte))
{
@@ -88,6 +88,12 @@ public static T[] Array(int count)
return result;
}
+ public static T Value(int? seed = null)
+ {
+ var random = new Random(seed ?? Seed);
+ return GenerateValue(random);
+ }
+
public static readonly byte[] s_encodingMap = {
65, 66, 67, 68, 69, 70, 71, 72, //A..H
73, 74, 75, 76, 77, 78, 79, 80, //I..P