---
title: "Get deterministic GPU compute results in C#"
url: https://recursiveai.org/onegpu/cookbook/deterministic-gpu-results/
description: "Get repeatable floating-point GPU results in C# with OneGpu’s deterministic mode. Includes a runnable matrix product and bitwise comparison."
version: "1.0.0"
---

# Get deterministic GPU compute results in C#

**OneGpu** is a free, open-source GPU compute and rendering library for .NET from Recursive AI, on Vulkan, Metal and WebGPU. MIT or Apache-2.0, no bundled native binaries.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneGpu.Backends) · [GitHub](https://github.com/recursive-ai-oss/onegpu-csharp) · [Docs](https://recursiveai.org/onegpu/docs/) · [Download example (.zip)](https://recursiveai.org/onegpu/cookbook/deterministic-gpu-results/deterministic-gpu-results.zip)

Repeat floating-point results on the same GPU and driver, not across vendors or drivers. Linux and Windows require Vulkan 1.3.

```shell
dotnet new console
dotnet add package RecursiveAI.OneGpu.Backends
dotnet add package RecursiveAI.OneGpu.Kernels
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.


```csharp
using RecursiveAI.OneGpu;
using RecursiveAI.OneGpu.Kernels;

using var device = GpuBackends.CreateDevice(
    new GpuDeviceOptions { Adapter = "discrete" });
using var left = device.CreateBuffer<float>(new float[] { 1, 2, 3, 4 });
using var right = device.CreateBuffer<float>(new float[] { 5, 6, 7, 8 });
using var output = device.CreateBuffer<float>(4);
using var gemm = new Gemm(device, GemmElementType.F32,
    GpuKernelMode.Deterministic);
var first = new float[4];
var second = new float[4];
foreach (var result in new[] { first, second })
{
    var encoder = device.BeginCommands();
    gemm.Encode(encoder, new GemmProblem(2, 2, 2), left, right, output);
    device.Submit(encoder);
    await output.ReadAsync(result);
}
Console.WriteLine(string.Join(", ", first));
Console.WriteLine($"Identical bits: {first.Select(BitConverter.SingleToInt32Bits)
    .SequenceEqual(second.Select(BitConverter.SingleToInt32Bits))}");
```

The input buffers `left` and `right` hold row-major 2 × 2 matrices. The example project has `ImplicitUsings` enabled, which supplies `System.Linq` for `Select` and `SequenceEqual`. `Gemm` means general matrix multiplication. The second readback completes before the buffers and kernel are disposed. This output was recorded on an NVIDIA GeForce RTX 4070 with Vulkan.

A wrong shape, stride, size or offset throws `GpuKernelShapeException`; an unsupported capability throws `GpuUnsupportedException` naming what is missing.

Unzip [the example](https://recursiveai.org/onegpu/cookbook/deterministic-gpu-results/deterministic-gpu-results.zip), then `dotnet run`.

Prints the matrix product and compares the bits from two submissions:

```text
19, 22, 43, 50
Identical bits: True
```

## Variations

### Select a GPU by name

Replace the device creation in the program with this. The name must match an adapter on your machine; this version produced the same output on the RTX 4070:

```csharp
using var device = GpuBackends.CreateDevice(
    new GpuDeviceOptions { Adapter = "NVIDIA GeForce RTX 4070" });
```

## Related recipes

- [Time a GPU compute pass](https://recursiveai.org/onegpu/cookbook/time-a-compute-pass/)
- [Run WebGPU compute in Blazor WebAssembly](https://recursiveai.org/onegpu/cookbook/webgpu-compute-in-blazor-webassembly/)

## The short answer

Pass `GpuKernelMode.Deterministic` when constructing a supported OneGpu kernel family. In OneGpu 1.0.0, that mode applies to GEMM, reductions, softmax and attention. Keep the input data, GPU and driver the same when you need bit-repeatable results. The [release’s determinism contract](https://github.com/recursive-ai-oss/onegpu-csharp/blob/5d3317caecb82fedd96642e54b0ab33bcb9759c5/README.md#determinism-and-tolerances) explicitly excludes bit identity across vendors or drivers.

The example checks the stored float bits, not just rounded text. Two results can print the same decimal text while differing in their binary representation. `BitConverter.SingleToInt32Bits` exposes each float’s representation; comparing those integers checks what the example claims.

## What does non-deterministic mean?

For this task, it means repeated computations with the same input can produce different output bits. That is a different question from whether both outputs are acceptably close to a reference result. A tolerance test can accept both while a bitwise comparison rejects them.

OneGpu’s default mode is `Fast`. The release documentation says a fast kernel may sum in any order and use fused multiply-add. Its deterministic mode fixes the reduction and accumulation order, avoids float atomics, and avoids choices that depend on occupancy or subgroup scheduling. It changes the execution rules of the supported kernels; it does not change float32 into exact real-number arithmetic.

Choose deterministic mode when a saved reference output or a repeatability check requires matching bits on the same environment. Use a numerical tolerance when the requirement is closeness to a mathematical reference rather than repeatability of one implementation. Keep those two checks separate in test output so a mismatch tells you which requirement failed.

## How do I get deterministic GPU compute results in C#?

Create the deterministic kernel before encoding the work, as the snippet does. Reuse that kernel for both submissions, keep the operands unchanged, and wait for each readback before comparing the arrays. Setting a random seed would not configure this kernel’s accumulation order; the mode is an explicit constructor argument.

The sample’s matrices are deliberately small enough to inspect: the first output is `1 × 5 + 2 × 7`, which is 19. The remaining cells are 22, 43 and 50. These inputs show the complete upload, submission and readback path without any external files.

For a larger workload, retain the bitwise check but use the application’s actual matrices. Record the package version, GPU and driver alongside reference outputs. After a driver change, establish the reference again rather than interpreting the old bit pattern as a portable specification. Other OneGpu kernel families give the same bits in both modes according to the release documentation; deterministic mode is not a separate cross-device numerical format.
