Skip to content

Commit e216340

Browse files
Add TensorPrimitives benchmarks.
1 parent 0898582 commit e216340

5 files changed

Lines changed: 270 additions & 5 deletions

File tree

src/benchmarks/micro/MicroBenchmarks.csproj

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@
8888
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
8989
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
9090
</ItemGroup>
91+
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(_TargetFrameworkVersionWithoutV)' &gt;= '8.0'">
92+
<!-- we want both net8.0 and net9.0 targets to use the 9.0.0 version of the NuGet package (since this is where the generic math APIs were first added) -->
93+
<PackageReference Include="System.Numerics.Tensors" Version="$(SystemThreadingChannelsPackageVersion)" />
94+
</ItemGroup>
9195

9296
<ItemGroup>
9397
<ProjectReference Include="..\..\harness\BenchmarkDotNet.Extensions\BenchmarkDotNet.Extensions.csproj" />
@@ -212,9 +216,10 @@
212216
</ItemGroup>
213217

214218
<ItemGroup Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' Or ('$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(_TargetFrameworkVersionWithoutV)' &lt; '8.0')">
215-
<Compile Remove="libraries\System.Buffers\SearchValuesByteTests.cs" />
216-
<Compile Remove="libraries\System.Buffers\SearchValuesCharTests.cs" />
217-
<Compile Remove="libraries\System.Text.Encoding\Perf.Ascii.cs" />
219+
<Compile Remove="libraries\System.Buffers\SearchValuesByteTests.cs" />
220+
<Compile Remove="libraries\System.Buffers\SearchValuesCharTests.cs" />
221+
<Compile Remove="libraries\System.Text.Encoding\Perf.Ascii.cs" />
222+
<Compile Remove="libraries\System.Numerics.Tensors\*.cs" />
218223
</ItemGroup>
219224

220225
<!-- This is not removing things from older Net versions, it is removing from newer Net versions -->
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using BenchmarkDotNet.Attributes;
6+
using BenchmarkDotNet.Extensions;
7+
using MicroBenchmarks;
8+
9+
namespace System.Numerics.Tensors.Tests
10+
{
11+
[BenchmarkCategory(Categories.Libraries, Categories.SIMD, Categories.JIT)]
12+
[GenericTypeArguments(typeof(int))]
13+
public class Perf_BinaryIntegerTensorPrimitives<T>
14+
where T : unmanaged, IBinaryInteger<T>
15+
{
16+
[Params(128, 6 * 512 + 7)]
17+
public int BufferLength;
18+
19+
private T[] _source1;
20+
private T[] _destination;
21+
22+
[GlobalSetup]
23+
public void Init()
24+
{
25+
_source1 = ValuesGenerator.Array<T>(BufferLength, seed: 42);
26+
_destination = new T[BufferLength];
27+
}
28+
29+
#region Unary Operations
30+
[Benchmark]
31+
public void LeadingZeroCount() => TensorPrimitives.LeadingZeroCount<T>(_source1, _destination);
32+
33+
[Benchmark]
34+
public void OnesComplement() => TensorPrimitives.OnesComplement<T>(_source1, _destination);
35+
36+
[Benchmark]
37+
public void PopCount() => TensorPrimitives.PopCount<T>(_source1, _destination);
38+
39+
[Benchmark]
40+
public void ShiftLeft() => TensorPrimitives.ShiftLeft<T>(_source1, shiftAmount: 3, _destination);
41+
42+
[Benchmark]
43+
public void TrailingZeroCount() => TensorPrimitives.TrailingZeroCount<T>(_source1, _destination);
44+
#endregion
45+
}
46+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using BenchmarkDotNet.Attributes;
6+
using BenchmarkDotNet.Extensions;
7+
using MicroBenchmarks;
8+
using System.Linq;
9+
10+
namespace System.Numerics.Tensors.Tests
11+
{
12+
[BenchmarkCategory(Categories.Libraries, Categories.SIMD, Categories.JIT)]
13+
[GenericTypeArguments(typeof(float))]
14+
[GenericTypeArguments(typeof(double))]
15+
public class Perf_FloatingPointTensorPrimitives<T>
16+
where T : unmanaged, IFloatingPointIeee754<T>
17+
{
18+
[Params(128, 6 * 512 + 7)]
19+
public int BufferLength;
20+
21+
private T[] _source1;
22+
private T[] _source2;
23+
private T[] _source3;
24+
private T _scalar1;
25+
private T[] _ones;
26+
private T[] _destination;
27+
28+
[GlobalSetup]
29+
public void Init()
30+
{
31+
_source1 = ValuesGenerator.Array<T>(BufferLength, seed: 42);
32+
_source2 = ValuesGenerator.Array<T>(BufferLength, seed: 43);
33+
_source3 = ValuesGenerator.Array<T>(BufferLength, seed: 44);
34+
_scalar1 = ValuesGenerator.Value<T>(seed: 45);
35+
_ones = Enumerable.Repeat(T.One, BufferLength).ToArray();
36+
_destination = new T[BufferLength];
37+
}
38+
39+
#region Unary Operations
40+
[Benchmark]
41+
public void AtanPi() => TensorPrimitives.AtanPi<T>(_source1, _destination);
42+
43+
[Benchmark]
44+
public void Exp() => TensorPrimitives.Exp<T>(_source1, _destination);
45+
46+
[Benchmark]
47+
public void Log() => TensorPrimitives.Log<T>(_source1, _destination);
48+
49+
[Benchmark]
50+
public void Round() => TensorPrimitives.Round<T>(_source1, _destination);
51+
52+
[Benchmark]
53+
public void Sin() => TensorPrimitives.Sin<T>(_source1, _destination);
54+
55+
[Benchmark]
56+
public void Sinh() => TensorPrimitives.Sinh<T>(_source1, _destination);
57+
58+
[Benchmark]
59+
public void Sigmoid() => TensorPrimitives.Sigmoid<T>(_source1, _destination);
60+
61+
[Benchmark]
62+
public void Sqrt() => TensorPrimitives.Sqrt<T>(_source1, _destination);
63+
64+
[Benchmark]
65+
public void Truncate() => TensorPrimitives.Truncate<T>(_source1, _destination);
66+
#endregion
67+
68+
#region Binary/Ternary Operations
69+
[Benchmark]
70+
public void FusedMultiplyAdd_Vectors() => TensorPrimitives.FusedMultiplyAdd<T>(_source1, _source2, _source3, _destination);
71+
72+
[Benchmark]
73+
public void FusedMultiplyAdd_ScalarAddend() => TensorPrimitives.FusedMultiplyAdd(_source1, _scalar1, _source2, _destination);
74+
75+
[Benchmark]
76+
public void FusedMultiplyAdd_ScalarMultiplier() => TensorPrimitives.FusedMultiplyAdd(_source1, _source2, _scalar1, _destination);
77+
78+
[Benchmark]
79+
public void Ieee754Remainder_Vector() => TensorPrimitives.Ieee754Remainder<T>(_source1, _source2, _destination);
80+
81+
[Benchmark]
82+
public void Ieee754Remainder_ScalarDividend() => TensorPrimitives.Ieee754Remainder(_scalar1, _source1, _destination);
83+
84+
[Benchmark]
85+
public void Ieee754Remainder_ScalarDivisor() => TensorPrimitives.Ieee754Remainder(_source1, _scalar1, _destination);
86+
87+
[Benchmark]
88+
public void Pow_Vectors() => TensorPrimitives.Pow<T>(_source1, _ones, _destination);
89+
90+
[Benchmark]
91+
public void Pow_ScalarBase() => TensorPrimitives.Pow(_scalar1, _ones, _destination);
92+
93+
[Benchmark]
94+
public void Pow_ScalarExponent() => TensorPrimitives.Pow(_source1, T.One, _destination);
95+
#endregion
96+
97+
#region Reducers
98+
[Benchmark]
99+
public T CosineSimilarity() => TensorPrimitives.CosineSimilarity<T>(_source1, _source2);
100+
101+
[Benchmark]
102+
public T Distance() => TensorPrimitives.Distance<T>(_source1, _source2);
103+
#endregion
104+
}
105+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using BenchmarkDotNet.Attributes;
6+
using BenchmarkDotNet.Extensions;
7+
using MicroBenchmarks;
8+
using System.Linq;
9+
10+
namespace System.Numerics.Tensors.Tests
11+
{
12+
[BenchmarkCategory(Categories.Libraries, Categories.SIMD, Categories.JIT)]
13+
[GenericTypeArguments(typeof(int))]
14+
[GenericTypeArguments(typeof(float))]
15+
[GenericTypeArguments(typeof(double))]
16+
public class Perf_NumberTensorPrimitives<T>
17+
where T : INumber<T>, IBitwiseOperators<T, T, T>
18+
{
19+
[Params(128, 6 * 512 + 7)]
20+
public int BufferLength;
21+
22+
private T[] _source1;
23+
private T[] _source2;
24+
private T[] _source3;
25+
private T _scalar1;
26+
private T[] _ones;
27+
private T[] _destination;
28+
29+
[GlobalSetup]
30+
public void Init()
31+
{
32+
_source1 = ValuesGenerator.Array<T>(BufferLength, seed: 42);
33+
_source2 = ValuesGenerator.Array<T>(BufferLength, seed: 43);
34+
_source3 = ValuesGenerator.Array<T>(BufferLength, seed: 44);
35+
_scalar1 = ValuesGenerator.Value<T>(seed: 45);
36+
_ones = Enumerable.Repeat(T.One, BufferLength).ToArray();
37+
_destination = new T[BufferLength];
38+
}
39+
40+
#region Unary Operations
41+
[Benchmark]
42+
public void Abs() => TensorPrimitives.Abs<T>(_source1, _destination);
43+
44+
[Benchmark]
45+
public void Negate() => TensorPrimitives.Abs<T>(_source1, _destination);
46+
#endregion
47+
48+
#region Binary/Ternary Operations
49+
[Benchmark]
50+
public void Add_Vector() => TensorPrimitives.Add<T>(_source1, _source2, _destination);
51+
52+
[Benchmark]
53+
public void Add_Scalar() => TensorPrimitives.Add(_source1, _scalar1, _destination);
54+
55+
[Benchmark]
56+
public void AddMultiply_Vectors() => TensorPrimitives.AddMultiply<T>(_source1, _source2, _source3, _destination);
57+
58+
[Benchmark]
59+
public void AddMultiply_ScalarAddend() => TensorPrimitives.AddMultiply(_source1, _scalar1, _source2, _destination);
60+
61+
[Benchmark]
62+
public void AddMultiply_ScalarMultiplier() => TensorPrimitives.AddMultiply(_source1, _source2, _scalar1, _destination);
63+
64+
[Benchmark]
65+
public void BitwiseAnd_Vector() => TensorPrimitives.BitwiseAnd<T>(_source1, _source2, _destination);
66+
67+
[Benchmark]
68+
public void BitwiseAnd_Scalar() => TensorPrimitives.BitwiseAnd(_source1, _scalar1, _destination);
69+
70+
[Benchmark]
71+
public void Divide_Vector() => TensorPrimitives.Divide<T>(_source1, _ones, _destination);
72+
73+
[Benchmark]
74+
public void Divide_Scalar() => TensorPrimitives.Divide(_source1, T.One, _destination);
75+
76+
[Benchmark]
77+
public void Max_Vector() => TensorPrimitives.Max<T>(_source1, _source2, _destination);
78+
79+
[Benchmark]
80+
public void Max_Scalar() => TensorPrimitives.Max(_source1, _scalar1, _destination);
81+
82+
[Benchmark]
83+
public void MaxMagnitude_Vector() => TensorPrimitives.MaxMagnitude<T>(_source1, _source2, _destination);
84+
85+
[Benchmark]
86+
public void MaxMagnitude_Scalar() => TensorPrimitives.MaxMagnitude(_source1, _scalar1, _destination);
87+
#endregion
88+
89+
#region Reducers
90+
[Benchmark]
91+
public T Max() => TensorPrimitives.Max<T>(_source1);
92+
93+
[Benchmark]
94+
public T SumOfMagnitudes() => TensorPrimitives.SumOfMagnitudes<T>(_ones);
95+
96+
[Benchmark]
97+
public T SumOfSquares() => TensorPrimitives.SumOfSquares<T>(_ones);
98+
99+
[Benchmark]
100+
public int IndexOfMax() => TensorPrimitives.IndexOfMax<T>(_source1);
101+
#endregion
102+
}
103+
}

src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ public static T[] ArrayOfUniqueValues<T>(int count)
6767
/// For byte and sbyte values are built from Random.NextBytes, for other types GenerateValue is used
6868
/// to generate a random value in the appropriate range
6969
/// </summary>
70-
public static T[] Array<T>(int count)
70+
public static T[] Array<T>(int count, int? seed = null)
7171
{
7272
var result = new T[count];
7373

74-
var random = new Random(Seed);
74+
var random = new Random(seed ?? Seed);
7575

7676
if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte))
7777
{
@@ -88,6 +88,12 @@ public static T[] Array<T>(int count)
8888
return result;
8989
}
9090

91+
public static T Value<T>(int? seed = null)
92+
{
93+
var random = new Random(seed ?? Seed);
94+
return GenerateValue<T>(random);
95+
}
96+
9197
public static readonly byte[] s_encodingMap = {
9298
65, 66, 67, 68, 69, 70, 71, 72, //A..H
9399
73, 74, 75, 76, 77, 78, 79, 80, //I..P

0 commit comments

Comments
 (0)