Created
September 16, 2020 20:31
-
-
Save VictorNicollet/9827547e842d17da484df5fea3aa1bd7 to your computer and use it in GitHub Desktop.
SIMD benchmark: Vector.Abs on array or span
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; | |
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