Recursive AI

Check that two machines agree

All onemath recipes

Hash a fixed OneMath computation and compare the hash across machines, runtimes and CPU features: the cheapest way to confirm a deterministic simulation will stay in sync.

C#
using System.Security.Cryptography;
using RecursiveAI.OneMath;
 
// A fixed computation whose hash two machines (or a replay and the original) can compare.
var buffer = new byte[8 * 100_000];
for (int i = 0; i < 100_000; i++)
{
    double t = i * 0.001;
    double v = Math64.Sin(t) * Math64.Exp(-t / 50) + Math64.Atan2(t, 3) * Math64.Log1p(t);
    BitConverter.TryWriteBytes(buffer.AsSpan(8 * i), v);
}
Console.WriteLine($"sha256 {Convert.ToHexString(SHA256.HashData(buffer))[..32]}");

Built once in Release and run with the CPU’s vector instructions turned off step by step, and with the JIT’s tiering off:

Text
$ dotnet run -c Release
sha256 D72748EDFF396FE462CF2D674C8D342C
$ DOTNET_EnableAVX512F=0 dotnet run -c Release
sha256 D72748EDFF396FE462CF2D674C8D342C
$ DOTNET_EnableAVX2=0 dotnet run -c Release
sha256 D72748EDFF396FE462CF2D674C8D342C
$ DOTNET_EnableHWIntrinsic=0 dotnet run -c Release
sha256 D72748EDFF396FE462CF2D674C8D342C
$ DOTNET_TieredCompilation=0 dotnet run -c Release
sha256 D72748EDFF396FE462CF2D674C8D342C

Using it

  • Run the same program on each target you ship (x64 and arm64, NativeAOT, WebAssembly) and compare one line. If a hash ever differs, the cause is in your own code: a call to Math or MathF, a float sum in a different order, or a dependence on thread scheduling.
  • For a game, hash the simulation state every N frames and exchange it with peers; a mismatch then points at the first frame that diverged.

OneMath runs its own version of this, the hash matrix: fixed scenarios whose SHA-256 manifest must be equal on x64 JIT, scalar, AVX2 off, one thread and all cores, NativeAOT, browser WebAssembly (interpreted and AOT-compiled) and macOS arm64. Each 1.x release must also reproduce every line of the previous release’s manifest. See hash matrix.