-
-
Save Sergio0694/a7e2c443dc73121c4a9ad0521b477129 to your computer and use it in GitHub Desktop.
Benchmark with both Parallel.For and ComputeSharp for frames averaging
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.Runtime.CompilerServices; | |
using System.Threading.Tasks; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
using ComputeSharp; | |
namespace KinectBenchmark | |
{ | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
BenchmarkRunner.Run<AverageTest>(); | |
} | |
} | |
public class AverageTest | |
{ | |
[Params(150, 300)] | |
public int Frames; | |
public const int Width = 512; | |
public const int Height = 424; | |
// Source frames tensor (N*H*W) | |
public ushort[] FramesCpu; | |
// Frames buffer on the GPU | |
public ReadOnlyBuffer<int> FramesGpu; | |
// Result frame | |
public ushort[] ResultCpu; | |
// Result frame on the GPU | |
public ReadWriteBuffer<int> ResultGpu; | |
// Temporary result frame as int[] | |
public int[] Temp; | |
[GlobalSetup] | |
public void Setup() | |
{ | |
Random random = new Random(Frames); | |
ushort[] data = new ushort[Frames * Width * Height]; | |
for (int i = 0; i < data.Length; i++) | |
data[i] = (ushort)random.Next(0, ushort.MaxValue); | |
FramesCpu = data; | |
ResultCpu = new ushort[Width * Height]; | |
int[] temp = new int[data.Length]; | |
for (int i = 0; i < data.Length; i++) | |
temp[i] = data[i]; | |
Temp = temp; | |
FramesGpu = Gpu.Default.AllocateReadOnlyBuffer(temp); | |
ResultGpu = Gpu.Default.AllocateReadWriteBuffer<int>(Width * Height); | |
GpuAvg(); // Preload shader | |
} | |
[GlobalCleanup] | |
public void Cleanup() | |
{ | |
FramesGpu.Dispose(); | |
ResultGpu.Dispose(); | |
} | |
[Benchmark] | |
public void CpuAvg() | |
{ | |
int frames = Frames; | |
Parallel.For(0, Height, y => | |
{ | |
// Clear the target row | |
ResultCpu.AsSpan(y * Width, Width).Clear(); | |
ref ushort rSource = ref FramesCpu[y * Width]; | |
ref ushort rDest = ref ResultCpu[y * Width]; | |
// Compute the sum for the current row | |
for (int c = 0; c < frames; c++, rSource = Unsafe.Add(ref rSource, Width * Height)) | |
for (int x = 0; x < Width; x++) | |
Unsafe.Add(ref rDest, x) += Unsafe.Add(ref rSource, x); | |
// Average the row | |
for (int x = 0; x < Width; x++) | |
Unsafe.Add(ref rDest, x) /= (ushort)frames; | |
}); | |
} | |
[Benchmark] | |
public void GpuAvg() | |
{ | |
int frames = Frames; | |
ReadOnlyBuffer<int> source = FramesGpu; | |
ReadWriteBuffer<int> result = ResultGpu; // Local variables for closure | |
Gpu.Default.For(Height, Width, id => | |
{ | |
int offset = id.Y * Height + id.X; | |
result[offset] = 0; | |
// Depth sum (across frames) | |
for (int c = 0; c < frames; c++) | |
result[offset] += source[offset + Width * Height]; | |
// Average for the current pixel | |
result[offset] /= frames; | |
}); | |
// Copy result int[] array from the GPU | |
ResultGpu.GetData(Temp); | |
ref int rSource = ref Temp[0]; | |
ref ushort rDest = ref ResultCpu[0]; | |
int length = Width * Height; | |
// Convert to final ushort[] frame | |
for (int i = 0; i < length; i++) | |
Unsafe.Add(ref rDest, i) = (ushort)Unsafe.Add(ref rSource, i); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment