Browse Source

benchmarking benchmarking benchmarking

pull/34/head
Anton Firszov 9 years ago
parent
commit
57cc5c5f30
  1. 79
      src/ImageSharp46/Formats/Jpg/Components/Block8x8.cs
  2. 259
      tests/ImageSharp.Tests46/Formats/Jpg/Block8x8Tests.cs

79
src/ImageSharp46/Formats/Jpg/Components/Block8x8.cs

@ -1,6 +1,8 @@
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// ReSharper disable InconsistentNaming
namespace ImageSharp.Formats
@ -35,30 +37,47 @@ namespace ImageSharp.Formats
public const int VectorCount = 16;
public const int ScalarCount = VectorCount * 4;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void LoadFrom(Span<float> source)
{
fixed (Vector4* ptr = &V0L)
{
float* fp = (float*)ptr;
for (int i = 0; i < ScalarCount; i++)
{
fp[i] = source[i];
}
Marshal.Copy(source.Data, source.Offset, (IntPtr)ptr, ScalarCount);
//float* fp = (float*)ptr;
//for (int i = 0; i < ScalarCount; i++)
//{
// fp[i] = source[i];
//}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void CopyTo(Span<float> dest)
{
fixed (Vector4* ptr = &V0L)
{
float* fp = (float*)ptr;
for (int i = 0; i < ScalarCount; i++)
{
dest[i] = fp[i];
}
Marshal.Copy((IntPtr)ptr, dest.Data, dest.Offset, ScalarCount);
//float* fp = (float*)ptr;
//for (int i = 0; i < ScalarCount; i++)
//{
// dest[i] = fp[i];
//}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void LoadFrom(Block8x8* blockPtr, Span<float> source)
{
Marshal.Copy(source.Data, source.Offset, (IntPtr)blockPtr, ScalarCount);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void CopyTo(Block8x8* blockPtr, Span<float> dest)
{
Marshal.Copy((IntPtr)blockPtr, dest.Data, dest.Offset, ScalarCount);
}
internal unsafe void LoadFrom(Span<int> source)
{
fixed (Vector4* ptr = &V0L)
@ -104,7 +123,7 @@ namespace ImageSharp.Formats
}
/// <summary>
/// Used as a reference implementation for benchmarking
/// Reference implementation we can benchmark against
/// </summary>
internal unsafe void TransposeInto_PinningImpl(ref Block8x8 destination)
{
@ -145,9 +164,7 @@ namespace ImageSharp.Formats
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MultiplyAllInplace(Vector4 s)
{
@ -411,5 +428,41 @@ namespace ImageSharp.Formats
source.IDCTInto(ref dest, ref temp);
dest.CopyTo(block.Data);
}
public unsafe float this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
fixed (Block8x8* p = &this)
{
float* fp = (float*) p;
return fp[idx];
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
fixed (Block8x8* p = &this)
{
float* fp = (float*)p;
fp[idx] = value;
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe float GetScalarAt(Block8x8* blockPtr, int idx)
{
float* fp = (float*) blockPtr;
return fp[idx];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void SetScalarAt(Block8x8* blockPtr, int idx, float value)
{
float* fp = (float*)blockPtr;
fp[idx] = value;
}
}
}

259
tests/ImageSharp.Tests46/Formats/Jpg/Block8x8Tests.cs

@ -1,7 +1,11 @@
using System;
// Uncomment this to turn unit tests into benchmarks:
#define BENCHMARKING
using System;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using ImageSharp.Formats;
using Xunit;
@ -12,17 +16,84 @@ namespace ImageSharp.Tests.Formats.Jpg
// ReSharper disable once InconsistentNaming
public class Block8x8Tests : UtilityTestClassBase
{
#if BENCHMARKING
public const int Times = 1000000;
#else
public const int Times = 1;
#endif
public Block8x8Tests(ITestOutputHelper output) : base(output)
{
}
[Theory]
[InlineData(1)]
[InlineData(1000000)]
public void Load_Store_FloatArray(int times)
[Fact]
public void Indexer()
{
float sum = 0;
Measure(Times, () =>
{
Block8x8 block = new Block8x8();
for (int i = 0; i < Block8x8.ScalarCount; i++)
{
block[i] = i;
}
sum = 0;
for (int i = 0; i < Block8x8.ScalarCount; i++)
{
sum += block[i];
}
});
Assert.Equal(sum, 64f*63f*0.5f);
}
[Fact]
public unsafe void Indexer_GetScalarAt_SetScalarAt()
{
float sum = 0;
Measure(Times, () =>
{
Block8x8 block = new Block8x8();
for (int i = 0; i < Block8x8.ScalarCount; i++)
{
Block8x8.SetScalarAt(&block, i, i);
}
sum = 0;
for (int i = 0; i < Block8x8.ScalarCount; i++)
{
sum += Block8x8.GetScalarAt(&block, i);
}
});
Assert.Equal(sum, 64f * 63f * 0.5f);
}
[Fact]
public void Indexer_ReferenceBenchmarkWithArray()
{
float sum = 0;
float[] block = new float[64];
Measure(Times, () =>
{
//Block8x8 block = new Block8x8();
for (int i = 0; i < Block8x8.ScalarCount; i++)
{
block[i] = i;
}
sum = 0;
for (int i = 0; i < Block8x8.ScalarCount; i++)
{
sum += block[i];
}
});
Assert.Equal(sum, 64f * 63f * 0.5f);
}
[Fact]
public void Load_Store_FloatArray()
{
float[] data = new float[Block8x8.ScalarCount];
float[] mirror = new float[Block8x8.ScalarCount];
@ -30,24 +101,41 @@ namespace ImageSharp.Tests.Formats.Jpg
{
data[i] = i;
}
Measure(times, () =>
Measure(Times, () =>
{
Block8x8 v = new Block8x8();
v.LoadFrom(data);
v.CopyTo(mirror);
Block8x8 b = new Block8x8();
b.LoadFrom(data);
b.CopyTo(mirror);
});
Assert.Equal(data, mirror);
PrintLinearData((Span<float>)mirror);
//PrintLinearData((Span<float>)mirror);
}
[Theory]
[InlineData(1)]
[InlineData(1000000)]
public void Load_Store_IntArray(int times)
[Fact]
public unsafe void Load_Store_FloatArray_Ptr()
{
float[] data = new float[Block8x8.ScalarCount];
float[] mirror = new float[Block8x8.ScalarCount];
for (int i = 0; i < Block8x8.ScalarCount; i++)
{
data[i] = i;
}
Measure(Times, () =>
{
Block8x8 b = new Block8x8();
Block8x8.LoadFrom(&b, data);
Block8x8.CopyTo(&b, mirror);
});
Assert.Equal(data, mirror);
//PrintLinearData((Span<float>)mirror);
}
[Fact]
public void Load_Store_IntArray()
{
int[] data = new int[Block8x8.ScalarCount];
int[] mirror = new int[Block8x8.ScalarCount];
@ -55,7 +143,7 @@ namespace ImageSharp.Tests.Formats.Jpg
{
data[i] = i;
}
Measure(times, () =>
Measure(Times, () =>
{
Block8x8 v = new Block8x8();
v.LoadFrom(data);
@ -63,7 +151,7 @@ namespace ImageSharp.Tests.Formats.Jpg
});
Assert.Equal(data, mirror);
PrintLinearData((Span<int>)mirror);
//PrintLinearData((Span<int>)mirror);
}
[Fact]
@ -172,40 +260,37 @@ namespace ImageSharp.Tests.Formats.Jpg
public Block8x8 Buffer;
}
[Theory]
[InlineData(1)]
[InlineData(10000000)]
public void TranposeInto_Benchmark(int times)
[Fact]
public void TranposeInto_Benchmark()
{
BufferHolder source = new BufferHolder();
source.Buffer.LoadFrom(Create8x8FloatData());
BufferHolder dest = new BufferHolder();
Output.WriteLine($"TranposeInto_PinningImpl_Benchmark X {times} ...");
Output.WriteLine($"TranposeInto_PinningImpl_Benchmark X {Times} ...");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < times; i++)
for (int i = 0; i < Times; i++)
{
source.Buffer.TransposeInto(ref dest.Buffer);
}
sw.Stop();
Output.WriteLine($"TranposeInto_PinningImpl_Benchmark finished in {sw.ElapsedMilliseconds} ms");
}
[Theory]
[InlineData(1)]
[InlineData(10000000)]
public void TranposeInto_PinningImpl_Benchmark(int times)
[Fact]
public void TranposeInto_PinningImpl_Benchmark()
{
BufferHolder source = new BufferHolder();
source.Buffer.LoadFrom(Create8x8FloatData());
BufferHolder dest = new BufferHolder();
Output.WriteLine($"TranposeInto_PinningImpl_Benchmark X {times} ...");
Output.WriteLine($"TranposeInto_PinningImpl_Benchmark X {Times} ...");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < times; i++)
for (int i = 0; i < Times; i++)
{
source.Buffer.TransposeInto_PinningImpl(ref dest.Buffer);
}
@ -214,10 +299,8 @@ namespace ImageSharp.Tests.Formats.Jpg
Output.WriteLine($"TranposeInto_PinningImpl_Benchmark finished in {sw.ElapsedMilliseconds} ms");
}
[Theory]
[InlineData(1)]
[InlineData(10000000)]
public unsafe void TransposeInto_WithPointers_Benchmark(int times)
[Fact]
public unsafe void TransposeInto_WithPointers_Benchmark()
{
BufferHolder source = new BufferHolder();
source.Buffer.LoadFrom(Create8x8FloatData());
@ -227,10 +310,10 @@ namespace ImageSharp.Tests.Formats.Jpg
{
fixed (Block8x8* dPtr = &dest.Buffer)
{
Output.WriteLine($"TransposeInto_WithPointers_Benchmark X {times} ...");
Output.WriteLine($"TransposeInto_WithPointers_Benchmark X {Times} ...");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < times; i++)
for (int i = 0; i < Times; i++)
{
Block8x8.TransposeInto(sPtr, dPtr);
}
@ -318,110 +401,6 @@ namespace ImageSharp.Tests.Formats.Jpg
Print8x8Data(actualDestArray);
Assert.Equal(expectedDestArray, actualDestArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void TransposeMatrix(ref Matrix4x4 s, ref Matrix4x4 d)
{
d.M11 = s.M11;
d.M12 = s.M21;
d.M13 = s.M31;
d.M14 = s.M41;
d.M21 = s.M12;
d.M22 = s.M22;
d.M23 = s.M32;
d.M24 = s.M42;
d.M31 = s.M13;
d.M32 = s.M23;
d.M33 = s.M33;
d.M34 = s.M43;
d.M41 = s.M14;
d.M42 = s.M24;
d.M43 = s.M34;
d.M44 = s.M44;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void TransposeMatrixPtr(float* s, float* d)
{
for (int i = 0; i < 4; i++)
{
int i4 = i*4;
for (int j = 0; j < 4; j++)
{
d[j*4 + i] = s[i4 + j];
}
}
}
[Theory]
[InlineData(50000000)]
public void TransposeMatrix_Custom(int times)
{
Matrix4x4 s = new Matrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
Matrix4x4 d = new Matrix4x4();
Output.WriteLine($"TransposeMatrix_System X {times} ...");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < times; i++)
{
TransposeMatrix(ref s, ref d);
}
sw.Stop();
Output.WriteLine($"TransposeMatrix_System finished in {sw.ElapsedMilliseconds} ms");
Output.WriteLine(d.ToString());
}
[Theory]
[InlineData(50000000)]
public unsafe void TransposeMatrix_System(int times)
{
Matrix4x4 s = new Matrix4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
Matrix4x4 d = new Matrix4x4();
Output.WriteLine($"TransposeMatrix_System X {times} ...");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < times; i++)
{
d = Matrix4x4.Transpose(s);
}
sw.Stop();
Output.WriteLine($"TransposeMatrix_System finished in {sw.ElapsedMilliseconds} ms");
Output.WriteLine(d.ToString());
}
[Theory]
[InlineData(50000000)]
public unsafe void TransposeMatrix_Ptr(int times)
{
Matrix4x4 s = new Matrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
Matrix4x4 d = new Matrix4x4();
float* sPtr = (float*) &s;
float* dPtr = (float*) &d;
Output.WriteLine($"TransposeMatrix_System X {times} ...");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < times; i++)
{
TransposeMatrixPtr(sPtr,dPtr);
}
sw.Stop();
Output.WriteLine($"TransposeMatrix_System finished in {sw.ElapsedMilliseconds} ms");
Output.WriteLine(d.ToString());
}
}
}
Loading…
Cancel
Save