Skip to content

Instantly share code, notes, and snippets.

@VictorNicollet
Created September 16, 2020 20:31
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 VictorNicollet/9827547e842d17da484df5fea3aa1bd7 to your computer and use it in GitHub Desktop.
Save VictorNicollet/9827547e842d17da484df5fea3aa1bd7 to your computer and use it in GitHub Desktop.
SIMD benchmark: Vector.Abs on array or span
using System;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace Benchmarks
{
class Program
{
static void Main()
{
BenchmarkRunner.Run<Bench>();
Console.ReadKey();
}
}
public static class Implementations<T> where T : unmanaged
{
public static void AbsArr(T[] array, T[] result)
{
if (result.Length != array.Length)
{
throw new ArgumentOutOfRangeException(nameof(result));
}
int vLen = Vector<T>.Count;
int i;
for (i = 0; i <= array.Length - vLen; i += vLen)
{
Vector.Abs(new Vector<T>(array, i)).CopyTo(result, i);
}
}
public static void AbsSpan(Span<T> array, Span<T> result)
{
if (result.Length != array.Length)
{
throw new ArgumentOutOfRangeException(nameof(result));
}
int vLen = Vector<T>.Count;
int i;
for (i = 0; i <= array.Length - vLen; i += vLen)
{
Vector.Abs(new Vector<T>(array.Slice(i, vLen))).CopyTo(result.Slice(i, vLen));
}
}
public static void AbsSpanCast(Span<T> array, Span<T> result)
{
if (result.Length != array.Length)
{
throw new ArgumentOutOfRangeException(nameof(result));
}
var inVectors = MemoryMarshal.Cast<T, Vector<T>>(array);
var outVectors = MemoryMarshal.Cast<T, Vector<T>>(result);
int i;
for (i = 0; i < inVectors.Length; i++)
{
outVectors[i] = Vector.Abs(inVectors[i]);
}
}
public static void AbsSpanCastTemp(Span<T> array, Span<T> result)
{
if (result.Length != array.Length)
{
throw new ArgumentOutOfRangeException(nameof(result));
}
var inVectors = MemoryMarshal.Cast<T, Vector<T>>(array);
var outVectors = MemoryMarshal.Cast<T, Vector<T>>(result);
int i;
for (i = 0; i < inVectors.Length; i++)
{
var temp = Vector.Abs(inVectors[i]);
outVectors[i] = temp;
}
}
}
public class Bench
{
public float[] Data;
[Params(1, 10, 100, 1000)]
public int N;
[GlobalSetup]
public void GlobalSetup()
{
Data = Enumerable.Range(0, N * Vector<float>.Count).Select(i => (float)i).ToArray();
}
[Benchmark(Baseline = true)]
public void Array()
{
Implementations<float>.AbsArr(Data, Data);
}
[Benchmark]
public void Span()
{
Implementations<float>.AbsSpan(Data, Data);
}
[Benchmark]
public void SpanCast()
{
Implementations<float>.AbsSpanCast(Data, Data);
}
[Benchmark]
public void SpanTemp()
{
Implementations<float>.AbsSpanCastTemp(Data, Data);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment