Skip to content

Instantly share code, notes, and snippets.

@tannergooding
Created April 3, 2022 23:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tannergooding/c3bdb0b827b5cdac50621f3a5432d49b to your computer and use it in GitHub Desktop.
Save tannergooding/c3bdb0b827b5cdac50621f3a5432d49b to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
public unsafe class Proga
{
static void Main(string[] args)
{
BenchmarkSwitcher.FromAssembly(typeof(Proga).Assembly).Run(args);
}
}
[DisassemblyDiagnoser]
public unsafe class Benchmarks
{
private const int length = 1024 * 16;
private static IntPtr pData16;
private static IntPtr pData32;
private static IntPtr pData64;
[GlobalSetup]
public void Setup()
{
pData16 = (IntPtr)NativeMemory.AlignedAlloc(length, 16);
pData32 = (IntPtr)NativeMemory.AlignedAlloc(length, 32);
pData64 = (IntPtr)NativeMemory.AlignedAlloc(length, 64);
}
[GlobalCleanup]
public void Cleanup()
{
NativeMemory.AlignedFree((void*)pData16);
NativeMemory.AlignedFree((void*)pData32);
NativeMemory.AlignedFree((void*)pData64);
}
public IEnumerable<object[]> TestData()
{
yield return new object[] { length, (byte)42 };
yield return new object[] { length, (byte)42 };
yield return new object[] { length, (byte)42 };
}
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_1xV128_16(int length, byte v) => Contains_1xV128(pData16, length, v);
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_1xV128_32(int length, byte v) => Contains_1xV128(pData32, length, v);
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_1xV128_64(int length, byte v) => Contains_1xV128(pData64, length, v);
public bool Contains_1xV128(IntPtr pData, int length, byte v)
{
ref byte b = ref ((byte*)(pData))[0];
nuint len = (nuint)length;
Vector128<byte> vVec = Vector128.Create(v);
for (nuint i = 0; i < len; i += (nuint)(Vector128<byte>.Count))
{
Vector128<byte> v1 = Vector128.LoadUnsafe(ref b, i);
if (Vector128.Equals(v1, vVec) == Vector128<byte>.Zero)
{
continue;
}
return true;
}
return false;
}
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_2xV128_16(int length, byte v) => Contains_2xV128(pData16, length, v);
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_2xV128_32(int length, byte v) => Contains_2xV128(pData32, length, v);
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_2xV128_64(int length, byte v) => Contains_2xV128(pData64, length, v);
public bool Contains_2xV128(IntPtr pData, int length, byte v)
{
ref byte b = ref ((byte*)(pData))[0];
nuint len = (nuint)length;
Vector128<byte> vVec = Vector128.Create(v);
for (nuint i = 0; i < len; i += (nuint)(Vector128<byte>.Count * 2))
{
Vector128<byte> v1 = Vector128.LoadUnsafe(ref b, i);
Vector128<byte> v2 = Vector128.LoadUnsafe(ref b, i + (nuint)(Vector128<byte>.Count));
if ((Vector128.Equals(v1, vVec) | Vector128.Equals(v2, vVec)) == Vector128<byte>.Zero)
{
continue;
}
return true;
}
return false;
}
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_4xV128_16(int length, byte v) => Contains_4xV128(pData16, length, v);
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_4xV128_32(int length, byte v) => Contains_4xV128(pData32, length, v);
[Benchmark]
[ArgumentsSource(nameof(TestData))]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool Contains_4xV128_64(int length, byte v) => Contains_4xV128(pData64, length, v);
public bool Contains_4xV128(IntPtr pData, int length, byte v)
{
ref byte b = ref ((byte*)(pData))[0];
nuint len = (nuint)length;
Vector128<byte> vVec = Vector128.Create(v);
for (nuint i = 0; i < len; i += (nuint)(Vector128<byte>.Count * 4))
{
if ((Vector128.Equals(Vector128.LoadUnsafe(ref b, i), vVec) |
Vector128.Equals(Vector128.LoadUnsafe(ref b, i + (nuint)(Vector128<byte>.Count)), vVec) |
Vector128.Equals(Vector128.LoadUnsafe(ref b, i + (nuint)(Vector128<byte>.Count * 2)), vVec) |
Vector128.Equals(Vector128.LoadUnsafe(ref b, i + (nuint)(Vector128<byte>.Count * 3)), vVec)) == Vector128<byte>.Zero)
{
continue;
}
return true;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment