Created
September 4, 2022 17:08
-
-
Save kipters/176da3077e686aa6b5eb1ed0248ed0ff to your computer and use it in GitHub Desktop.
.NET 7 intrinsics benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
using System.Runtime.Intrinsics; | |
using System.Runtime.Intrinsics.X86; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
#if DEBUG | |
var testClass = new DotProductBenchmarks { Length = 8 }; | |
testClass.GlobalSetup(); | |
var implementations = typeof(DotProductBenchmarks) | |
.GetMethods() | |
.Where(m => m.GetCustomAttribute<BenchmarkAttribute>() is not null); | |
foreach (var method in implementations) | |
{ | |
var name = method.Name; | |
var result = method.Invoke(testClass, null); | |
Console.WriteLine($"{name}: {result}"); | |
} | |
Console.WriteLine($"{Vector64.IsHardwareAccelerated} {Vector128.IsHardwareAccelerated} {Vector256.IsHardwareAccelerated}"); | |
#else | |
BenchmarkRunner.Run<DotProductBenchmarks>(); | |
#endif | |
[MemoryDiagnoser] | |
public class DotProductBenchmarks | |
{ | |
[Params(8, 16, 32, 1024, 32768, 65536)] | |
public int Length; | |
private int[] First = Array.Empty<int>(); | |
private int[] Second = Array.Empty<int>(); | |
[GlobalSetup] | |
public void GlobalSetup() | |
{ | |
First = Enumerable.Range(0, Length).Select(_ => (int)(Random.Shared.Next() & 0x00FF)).ToArray(); | |
Second = Enumerable.Range(0, Length).Select(_ => (int)(Random.Shared.Next() & 0x00FF)).ToArray(); | |
} | |
[Benchmark] | |
public long Scalar() | |
{ | |
var acc = 0L; | |
for (var i = 0; i < Length; i++) | |
{ | |
acc += First[i] * Second[i]; | |
} | |
return acc; | |
} | |
[Benchmark] | |
public unsafe long Vectorized64() | |
{ | |
ref var f = ref MemoryMarshal.GetReference<int>(First); | |
ref var s = ref MemoryMarshal.GetReference<int>(Second); | |
var acc = Vector64<int>.Zero; | |
for (var i = 0; i < Length; i += 2) | |
{ | |
var offset = (nuint)i; | |
var a = Vector64.LoadUnsafe(ref f, offset); | |
var b = Vector64.LoadUnsafe(ref s, offset); | |
acc += a * b; | |
} | |
return Vector64.Sum(acc); | |
} | |
[Benchmark] | |
public unsafe long Vectorized128() | |
{ | |
ref var f = ref MemoryMarshal.GetReference<int>(First); | |
ref var s = ref MemoryMarshal.GetReference<int>(Second); | |
var acc = Vector128<int>.Zero; | |
for (var i = 0; i < Length; i += 4) | |
{ | |
var offset = (nuint)i; | |
var a = Vector128.LoadUnsafe(ref f, offset); | |
var b = Vector128.LoadUnsafe(ref s, offset); | |
acc += a * b; | |
} | |
return Vector128.Sum(acc); | |
} | |
[Benchmark] | |
public unsafe long Vectorized256() | |
{ | |
ref var f = ref MemoryMarshal.GetReference<int>(First); | |
ref var s = ref MemoryMarshal.GetReference<int>(Second); | |
var acc = Vector256<int>.Zero; | |
for (var i = 0; i < Length; i += 8) | |
{ | |
var offset = (nuint)i; | |
var a = Vector256.LoadUnsafe(ref f, offset); | |
var b = Vector256.LoadUnsafe(ref s, offset); | |
acc += a * b; | |
} | |
return Vector256.Sum(acc); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment