mirror of https://github.com/SixLabors/ImageSharp
2 changed files with 127 additions and 0 deletions
@ -0,0 +1,66 @@ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using BenchmarkDotNet.Attributes; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization |
|||
{ |
|||
public class UInt32ToSingle |
|||
{ |
|||
private float[] data; |
|||
|
|||
private const int Count = 64; |
|||
|
|||
[GlobalSetup] |
|||
public void Setup() |
|||
{ |
|||
this.data = new float[Count]; |
|||
} |
|||
|
|||
[Benchmark(Baseline = true)] |
|||
public void MagicMethod() |
|||
{ |
|||
ref Vector<float> b = ref Unsafe.As<float, Vector<float>>(ref this.data[0]); |
|||
|
|||
int n = Count / Vector<float>.Count; |
|||
|
|||
Vector<float> magick = new Vector<float>(32768.0f); |
|||
Vector<float> scale = new Vector<float>(255f) / new Vector<float>(256f); |
|||
|
|||
for (int i = 0; i < n; i++) |
|||
{ |
|||
// union { float f; uint32_t i; } u;
|
|||
// u.f = 32768.0f + x * (255.0f / 256.0f);
|
|||
// return (uint8_t)u.i;
|
|||
|
|||
ref Vector<float> d = ref Unsafe.Add(ref b, i); |
|||
Vector<float> x = d; |
|||
//x = Vector.Max(x, Vector<float>.Zero);
|
|||
//x = Vector.Min(x, Vector<float>.One);
|
|||
|
|||
x = (x * scale) + magick; |
|||
d = x; |
|||
} |
|||
} |
|||
|
|||
[Benchmark] |
|||
public void StandardSimd() |
|||
{ |
|||
int n = Count / Vector<float>.Count; |
|||
|
|||
ref Vector<float> b = ref Unsafe.As<float, Vector<float>>(ref this.data[0]); |
|||
|
|||
var scale = new Vector<float>(1f / 255f); |
|||
|
|||
for (int i = 0; i < n; i++) |
|||
{ |
|||
ref Vector<float> df = ref Unsafe.Add(ref b, i); |
|||
Vector<uint> du = Unsafe.As<Vector<float>, Vector<uint>>(ref df); |
|||
|
|||
Vector<float> v = Vector.ConvertToSingle(du); |
|||
v *= scale; |
|||
df = v; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using BenchmarkDotNet.Attributes; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization |
|||
{ |
|||
public class WidenBytesToUInt32 |
|||
{ |
|||
private byte[] source; |
|||
|
|||
private uint[] dest; |
|||
|
|||
private const int Count = 64; |
|||
|
|||
[GlobalSetup] |
|||
public void Setup() |
|||
{ |
|||
this.source = new byte[Count]; |
|||
this.dest = new uint[Count]; |
|||
} |
|||
|
|||
[Benchmark(Baseline = true)] |
|||
public void Standard() |
|||
{ |
|||
const int N = Count / 8; |
|||
|
|||
ref SimdUtils.Octet.OfByte sBase = ref Unsafe.As<byte, SimdUtils.Octet.OfByte>(ref this.source[0]); |
|||
ref SimdUtils.Octet.OfUInt32 dBase = ref Unsafe.As<uint, SimdUtils.Octet.OfUInt32>(ref this.dest[0]); |
|||
|
|||
for (int i = 0; i < N; i++) |
|||
{ |
|||
Unsafe.Add(ref dBase, i).LoadFrom(ref Unsafe.Add(ref sBase, i)); |
|||
} |
|||
} |
|||
|
|||
[Benchmark] |
|||
public void Simd() |
|||
{ |
|||
int n = Count / Vector<byte>.Count; |
|||
|
|||
ref Vector<byte> sBase = ref Unsafe.As<byte, Vector<byte>>(ref this.source[0]); |
|||
ref Vector<uint> dBase = ref Unsafe.As<uint, Vector<uint>>(ref this.dest[0]); |
|||
|
|||
for (int i = 0; i < n; i++) |
|||
{ |
|||
Vector<byte> b = Unsafe.Add(ref sBase, i); |
|||
|
|||
Vector.Widen(b, out Vector<ushort> s0, out Vector<ushort> s1); |
|||
Vector.Widen(s0, out Vector<uint> w0, out Vector<uint> w1); |
|||
Vector.Widen(s1, out Vector<uint> w2, out Vector<uint> w3); |
|||
|
|||
ref Vector<uint> d = ref Unsafe.Add(ref dBase, i * 4); |
|||
d = w0; |
|||
Unsafe.Add(ref d, 1) = w1; |
|||
Unsafe.Add(ref d, 2) = w2; |
|||
Unsafe.Add(ref d, 3) = w3; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue