Вот из-за этого:
// Initialize ILGPU.
Context context = Context.CreateDefault();
Accelerator accelerator = context.CreateCLAccelerator(1);//context.GetPreferredDevice(preferCPU: false) .CreateAccelerator(context);
// Load the data.
using MemoryBuffer1D<float, Stride1D.Dense> deviceData = accelerator.Allocate1D(input);
using MemoryBuffer1D<float, Stride1D.Dense> deviceOutput = accelerator.Allocate1D<float>(output);
// load / precompile the kernel
Action<Index1D, ArrayView<float>, ArrayView<float>> loadedKernel =
accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<float>, ArrayView<float>>(Kernel);
// finish compiling and tell the accelerator to start computing the kernel
loadedKernel((int)deviceOutput.Length, deviceData.View, deviceOutput.View);
accelerator.Synchronize();
Объяснение: ты в каждом тесте постоянно создаешь новые объекты, которые необходимы для работы фреймворка. Это должно быть тяжелые объекты (много содержат, тяжело инициализируются).
Вынеси их инициализацию из-вне метода в какой нибудь
Setup
метод. Раз уж ты пользуешься BenchmarkDotNet, то вот
помощь с этим
UPD: оптимизировал бенчмарк - теперь GPU быстрее
public class SampleBenchmark
{
static void Kernel(Index1D i, ArrayView<float> data, ArrayView<float> output)
{
output[i] = data[i % data.Length];
}
public static IEnumerable<object[]> Arguments => new[] {new object[]{new float[1000000], new float[1000000]} };
private float[] _outputBuffer = new float[1000000];
private float[] _inputBuffer = new float[1000000];
private Context? _context;
private Accelerator? _accelerator;
private Action<Index1D, ArrayView<float>, ArrayView<float>>? _loadedKernel;
private MemoryBuffer1D<float, Stride1D.Dense>? _deviceData;
private MemoryBuffer1D<float, Stride1D.Dense>? _deviceOutput;
[GlobalSetup]
public void Setup()
{
var random = new Random();
for (var i = 0; i < _inputBuffer.Length; i++)
{
_inputBuffer[i] = random.NextSingle();
}
_context = Context.CreateDefault();
_accelerator = _context.GetPreferredDevice(preferCPU: false).CreateAccelerator(_context);
_loadedKernel = _accelerator!.LoadAutoGroupedStreamKernel<Index1D, ArrayView<float>, ArrayView<float>>(Kernel);
_deviceData = _accelerator!.Allocate1D(_inputBuffer);
_deviceOutput = _accelerator!.Allocate1D(_outputBuffer);
}
[GlobalCleanup]
public void TearDown()
{
_context?.Dispose();
_accelerator?.Dispose();
_deviceData?.Dispose();
_deviceOutput?.Dispose();
}
[ArgumentsSource(nameof(Arguments))]
[Benchmark]
public void GPUTest(float[] input, float[] output)
{
// finish compiling and tell the accelerator to start computing the kernel
_loadedKernel!((int)_deviceOutput.Length, _deviceData.View, _deviceOutput.View);
_accelerator!.Synchronize();
}
[Benchmark]
[ArgumentsSource(nameof(Arguments))]
public void CpuTest(float[] input, float[] output)
{
for (var i = 0; i < input.Length; i++)
{
output[i] = input[i];
}
}
}
| Method | input | output | Mean | Error | StdDev |
|-------- |---------------- |---------------- |----------:|---------:|---------:|
| GPUTest | Single[1000000] | Single[1000000] | 61.18 us | 0.101 us | 0.095 us |
| CpuTest | Single[1000000] | Single[1000000] | 243.54 us | 3.114 us | 2.600 us |