namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization { using System; using System.Numerics; using System.Runtime.CompilerServices; using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Memory; /// /// This benchmark compares different methods for fetching memory data into /// checking if JIT has limitations. Normally SIMD acceleration should be here for all methods. /// public class VectorFetching { private float testValue; private float[] data; [Params(64)] public int InputSize { get; set; } [GlobalSetup] public void Setup() { this.data = new float[this.InputSize]; this.testValue = 42; for (int i = 0; i < this.InputSize; i++) { this.data[i] = i; } } [Benchmark(Baseline = true)] public void Baseline() { float v = this.testValue; for (int i = 0; i < this.data.Length; i++) { this.data[i] = this.data[i] * v; } } [Benchmark] public void FetchWithVectorConstructor() { Vector v = new Vector(this.testValue); for (int i = 0; i < this.data.Length; i += Vector.Count) { Vector a = new Vector(this.data, i); a = a * v; a.CopyTo(this.data, i); } } [Benchmark] public void FetchWithUnsafeCast() { Vector v = new Vector(this.testValue); ref Vector start = ref Unsafe.As>(ref this.data[0]); int n = this.InputSize / Vector.Count; for (int i = 0; i < n; i++) { ref Vector p = ref Unsafe.Add(ref start, i); Vector a = p; a = a * v; p = a; } } [Benchmark] public void FetchWithUnsafeCastNoTempVector() { Vector v = new Vector(this.testValue); ref Vector start = ref Unsafe.As>(ref this.data[0]); int n = this.InputSize / Vector.Count; for (int i = 0; i < n; i++) { ref Vector a = ref Unsafe.Add(ref start, i); a = a * v; } } [Benchmark] public void FetchWithSpanUtility() { Vector v = new Vector(this.testValue); Span span = new Span(this.data); ref Vector start = ref span.FetchVector(); int n = this.InputSize / Vector.Count; for (int i = 0; i < n; i++) { ref Vector a = ref Unsafe.Add(ref start, i); a = a * v; } } } }