Skip to content

Instantly share code, notes, and snippets.

@DBalashov
Created June 30, 2023 18:30
Show Gist options
  • Save DBalashov/b442dd7e157b73a6e0575ccca90a0afa to your computer and use it in GitHub Desktop.
Save DBalashov/b442dd7e157b73a6e0575ccca90a0afa to your computer and use it in GitHub Desktop.
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
#pragma warning disable CS8618
var summary = BenchmarkRunner.Run<MainTest>();
[SimpleJob(RuntimeMoniker.Net70)]
[WarmupCount(2)]
[IterationCount(2)]
// [MemoryDiagnoser]
public class MainTest
{
const int ITERATIONS = 10000;
[Params(128, 256, 512, 1024 * 1, 1024 * 2, 1024 * 3, 1024 * 4, 1024 * 5, 1024 * 6, 1024 * 7, 1024 * 8)]
public int N { get; set; }
int[] ints;
int findValue;
[IterationSetup]
public void Setup()
{
ints = Enumerable.Range(0, N).ToArray();
findValue = ints[^3];
}
[Benchmark]
public void FindSimple()
{
for (var iteration = 0; iteration < ITERATIONS; iteration++)
{
FindSimple_(ints, findValue);
}
}
[Benchmark]
public void FindSSE_128()
{
for (var iteration = 0; iteration < ITERATIONS; iteration++)
FindSSE_128_(ints, findValue);
}
[Benchmark]
public void FindSSE_256()
{
for (var iteration = 0; iteration < ITERATIONS; iteration++)
FindSSE_256_(ints, findValue);
}
static int FindSimple_(int[] data, int value)
{
foreach (var i in data)
if (i == value)
return i;
return -1;
}
static int FindSSE_128_(int[] data, int value)
{
var ints = MemoryMarshal.Cast<int, Vector128<int>>(data);
var compareValue = Vector128.Create(value);
var vectorLength = Vector128<int>.Count;
for (var i = 0; i < ints.Length; i++)
{
var result = Sse2.CompareEqual(ints[i], compareValue);
if (result == Vector128<int>.Zero) continue;
for (var k = 0; k < vectorLength; k++)
if (result.GetElement(k) != 0)
return i * vectorLength + k;
}
for (var i = ints.Length * vectorLength; i < data.Length; i++)
if (data[i] == value)
return i;
return -1;
}
static int FindSSE_256_(int[] data, int value)
{
var ints = MemoryMarshal.Cast<int, Vector256<int>>(data);
var compareValue = Vector256.Create(value);
var vectorLength = Vector256<int>.Count;
for (var i = 0; i < ints.Length; i++)
{
var result = Avx2.CompareEqual(ints[i], compareValue);
if (result == Vector256<int>.Zero) continue;
for (var k = 0; k < vectorLength; k++)
if (result.GetElement(k) != 0)
return i * vectorLength + k;
}
for (var i = ints.Length * vectorLength; i < data.Length; i++)
if (data[i] == value)
return i;
return -1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment