Example uses NuGet package ComputeSharp 3.1.0
using System.Diagnostics;
using ComputeSharp;
namespace GpuTestConsole
{
public class Program
{
static void Main(string[] args)
{
var sw = new Stopwatch();
// Input arrays
float[] input1 = { 1, 2, 3, 4 };
float[] input2 = { 5, 6, 7, 8 };
float[] input3 = { 9, 10, 11, 12 };
// Output array
float[] output = new float[input1.Length];
var gpu = GraphicsDevice.GetDefault();
Console.WriteLine($"GPU: {gpu.Name}");
Console.WriteLine($"Compute units: {gpu.ComputeUnits}");
// Allocate buffers once
using var inputBuffer = gpu.AllocateReadOnlyBuffer<float>(input1.Length);
using var outputBuffer = gpu.AllocateReadWriteBuffer<float>(output.Length);
// Create the kernel (without running it yet)
var kernel = new AddKernel(inputBuffer, inputBuffer, outputBuffer);
// First computation
inputBuffer.CopyFrom(input1);
kernel.InputBuffer2.CopyFrom(input2); // Dynamically set second input buffer
sw.Start();
gpu.For(input1.Length, kernel);
// Copy result
outputBuffer.CopyTo(output);
Console.WriteLine($"Result 1: {string.Join(", ", output)} ({sw.ElapsedMilliseconds} ms)");
// Second computation with new inputs
inputBuffer.CopyFrom(input3);
kernel.InputBuffer2.CopyFrom(input1);
sw.Restart();
gpu.For(input1.Length, kernel);
outputBuffer.CopyTo(output);
Console.WriteLine($"Result 2: {string.Join(", ", output)} ({sw.ElapsedMilliseconds} ms)");
}
}
[GeneratedComputeShaderDescriptor]
[ThreadGroupSize(DefaultThreadGroupSizes.X)]
public partial struct AddKernel : IComputeShader
{
public ReadOnlyBuffer<float> InputBuffer1;
public ReadOnlyBuffer<float> InputBuffer2;
public ReadWriteBuffer<float> OutputBuffer;
public AddKernel(ReadOnlyBuffer<float> input1, ReadOnlyBuffer<float> input2, ReadWriteBuffer<float> output)
{
InputBuffer1 = input1;
InputBuffer2 = input2;
OutputBuffer = output;
}
/*
Aandachtspunten bij Execute
Thread Safety:
De GPU voert de Execute-functie parallel uit voor elk element.
Vermijd gedeelde variabelen (globals) en zorg dat elke thread alleen zijn eigen index gebruikt.
Thread Index:
Gebruik ThreadIds.X voor de 1D-index. Voor 2D- of 3D-berekeningen kun je ook ThreadIds.Y en ThreadIds.Z gebruiken.
Controleer altijd of de thread binnen het bereik van de buffer zit om out-of-bounds fouten te voorkomen.
Buffer Types:
Gebruik ReadOnlyBuffer<T> voor buffers die niet worden gewijzigd.
Gebruik ReadWriteBuffer<T> voor buffers die worden gelezen en geschreven.
Debugging:
Fouten in GPU-shaders kunnen lastig te debuggen zijn. Controleer of alle indexberekeningen correct zijn en zorg dat buffers voldoende groot zijn.
Prestatieoptimalisatie:
Voorkom onnodige synchronisaties tussen CPU en GPU.
Combineer meerdere kleine berekeningen in één kernel om overhead te verminderen.
*/
public void Execute()
{
int i = ThreadIds.X;
OutputBuffer[i] = InputBuffer1[i] + InputBuffer2[i];
}
}
}
917800cookie-checkC# Running computations on GPU