Recursive AI

Speed at 1.0

All onegpu docs

Note: in the README’s words, these figures were “Measured through onemodel’s RecursiveAI.OneModel.Gpu”. That package isn’t released yet; OneModel’s GPU support is coming in a later OneModel release, so the figures can’t be reproduced with the released packages.

The harness and the full method are in onemodel-csharp, tools/bar.sh and docs/bench.md. The models are onemodel's reference set: MiniLM-L6, BERT-base, ResNet-50, MobileNetV3, DBNet, CRNN and Whisper-small (encoder and decoder), in float32, float16 and dynamically quantized 8-bit forms.

Speed is judged against the reference provider on the same machine and the same model file; ratio is ours divided by the reference, so lower is better. The bar is 1.5 on a desktop (target 1.15) and 2.5 in a browser (target 1.5). met is a ratio above the target and within the bar, target is a ratio within the target, missed is above the bar. Only gate rows are judged (the reference ran every compute node on its GPU, read from its own placement log and, for Core ML, its compute plan); information rows are listed with their ratio and never judged. Every row runs a model through onemodel's RecursiveAI.OneModel.Gpu on these packages at their 1.0.0 code, fast mode, validation layers off, host arrays in and out, the median of warm runs (Linux 20, Apple M2 10, Chrome 10 per page) in one benchmark-queue job per group of rows, each group alone on its machine. Load average sampled every 5 s before, during and after is in every row of the jsonl; the one-minute load average at the start of a group still carries the harness's own CPU reference runs of the group before it. Reference versions: ONNX Runtime 1.31.1 with the onnxruntime-ep-webgpu 0.4.0 plugin (Dawn over Vulkan on Linux, over Metal on macOS), Core ML through the same wheel on GPU compute units, onnxruntime-web 1.31.1.

Linux, RTX 4070 (Vulkan, driver 595.99.02), Ryzen 9 7950X3D, 32 threads; reference: WebGPU provider

Three groups of rows, each alone on the machine. Gate rows 14 of 20: all met, worst ResNet-50 float32 at batch 8 (1.40) and BERT float32 at batch 8 (1.35); the other twelve are at or below the 1.15 target. The int8 rows are information rows: the reference leaves MatMulInteger, DynamicQuantizeLinear, QuantizeLinear or ConvInteger to its CPU provider, so those rows are not a like-for-like comparison. CUDA and onemodel CPU columns were not run for the gate.

rowours ms (GPU kernels)referenceref msours / refclassverdictother provider
minilm_fp32_b11.69 (1.17)WebGPU EP4.3090.39gatetarget-
minilm_fp32_b85.5 (4.83)WebGPU EP6.40.86gatetarget-
minilm_fp16_b12.24 (1.42)WebGPU EP3.9820.56gatetarget-
minilm_int8_b12.09 (1.37)WebGPU EP48.5660.04informationtarget-
bert_fp32_b16.49 (5.58)WebGPU EP7.4710.87gatetarget-
bert_fp32_b831.19 (30.35)WebGPU EP23.1881.35gatemet-
bert_int8_b16.33 (5.05)WebGPU EP115.7860.05informationtarget-
resnet50_fp32_b13.18 (2.7)WebGPU EP3.730.85gatetarget-
resnet50_fp32_b816.44 (15.21)WebGPU EP11.7731.40gatemet-
resnet50_fp16_b13.87 (3.07)WebGPU EP4.0190.96gatetarget-
resnet50_int8_b14.36 (3.39)WebGPU EP104.2080.04informationtarget-
mobilenet_fp32_b11.45 (0.99)WebGPU EP1.8990.76gatetarget-
mobilenet_fp32_b83.53 (2.74)WebGPU EP3.6660.96gatetarget-
mobilenet_int8_b13.23 (1.96)WebGPU EP112.8910.03informationtarget-
dbnet_fp32_b12.48 (1.8)WebGPU EP3.60.69gatetarget-
crnn_fp32_b10.95 (0.52)WebGPU EP19.5940.05gatetarget-
whisper_enc_b157.4 (56.1)WebGPU EP52.1421.10gatetarget-
whisper_dec_b114.37 (12.38)WebGPU EP13.551.06gatetarget-
whisper_enc_int8_b132.88 (31.46)WebGPU EP650.5380.05informationtarget-
whisper_dec_int8_b110.45 (7.95)WebGPU EP184.2550.06informationtarget-

Apple M2 (Metal, macOS 27.0.1); reference: whichever gate configuration of Core ML (GPU compute units) and the WebGPU provider on Metal took less time

Three groups in the benchmark queue, 10 runs per row. Gate rows 14 of 20: twelve are met, two are misses for 1.0: ResNet-50 float32 at batch 1 (2.16) and batch 8 (2.21) against Core ML on the GPU (6.07 ms and 35.27 ms; Core ML MLProgram on the GPU computes in float32 to 1e-6, so it is a fair reference). Against the WebGPU provider on Metal the same rows are 0.82 (13.09 against 15.94 ms) and 0.81 (77.94 against 95.71 ms). The miss is documented and ships: the levers left are per-model weight preparation for contiguous 3x3 reads and a Winograd F(2x2,3x3) kernel, estimated at about 1.8 times Core ML at batch 8, so not enough to close it. MobileNetV3 float32 at batch 8 (1.16) is just above the target. The int8 rows are information rows (MatMulInteger, DynamicQuantizeLinear and ConvInteger on the reference's CPU provider).

rowours ms (GPU kernels)referenceref msours / refclassverdictother provider
minilm_fp32_b16.67 (6.19)WebGPU EP9.7690.68gatetargetCore ML (GPU) 10.404 (information)
minilm_fp32_b825.91 (25.13)WebGPU EP40.7090.64gatetargetCore ML (GPU) 72.514 (information)
minilm_fp16_b110.61 (9.72)WebGPU EP9.551.11gatetargetCore ML (GPU) 11.91 (information)
minilm_int8_b112.65 (11.61)Core ML (GPU)6.9171.83informationmissedWebGPU EP 18.781 (information)
bert_fp32_b124.7 (23.99)WebGPU EP41.4560.60gatetargetCore ML (GPU) 66.332 (information)
bert_fp32_b8156.11 (155.02)WebGPU EP221.2780.71gatetargetCore ML (GPU) 512.805 (information)
bert_int8_b149.59 (48.7)Core ML (GPU)29.1281.70informationmissedWebGPU EP 53.508 (information)
resnet50_fp32_b113.09 (12.5)Core ML (GPU)6.0682.16gatemissedWebGPU EP 15.937 (gate)
resnet50_fp32_b877.94 (76.77)Core ML (GPU)35.2682.21gatemissedWebGPU EP 95.712 (gate)
resnet50_fp16_b113.13 (12.41)WebGPU EP12.4621.05gatetargetCore ML (GPU) 5.409 (information)
resnet50_int8_b121.87 (20.79)Core ML (GPU)18.5411.18informationmetWebGPU EP 69.618 (information)
mobilenet_fp32_b15.33 (4.83)WebGPU EP5.0451.06gatetargetCore ML (GPU) 9.886 (information)
mobilenet_fp32_b821.04 (19.88)WebGPU EP18.0721.16gatemetCore ML (GPU) 28.363 (information)
mobilenet_int8_b111.17 (9.89)Core ML (GPU)13.9240.80informationtargetWebGPU EP 50.786 (information)
dbnet_fp32_b117.47 (16.44)WebGPU EP17.8590.98gatetargetCore ML (GPU) 13.791 (information)
crnn_fp32_b12.79 (2.37)WebGPU EP48.1420.06gatetargetCore ML (GPU) 1.534 (information)
whisper_enc_b1371.95 (370.23)WebGPU EP476.4610.78gatetargetCore ML (GPU) 1047.15 (information)
whisper_dec_b188.27 (85.95)WebGPU EP79.5861.11gatetargetCore ML (GPU) 132.07 (information)
whisper_enc_int8_b1609.78 (607.89)WebGPU EP563.71.08informationtargetCore ML (GPU) 567.703 (information)
whisper_dec_int8_b186.91 (85.48)Core ML (GPU)48.9241.78informationmissedWebGPU EP 104.941 (information)

Chrome 155 on the RTX 4070, WebGPU (ahead-of-time compiled page); reference: onnxruntime-web WebGPU provider

Two groups, each alone on the machine, ten warm runs per page, same adapter. The twelve float32 rows; every one is within the 2.5 bar and eleven within the 1.5 target (ResNet-50 batch 8, 1.54, is the only one above). The float16 rows decline in this browser (no shader-f16 on this Chrome) and the int8 rows are information, so none is a bar row here; they run (fast and exact, two-run output identical) in the device matrix below.

rowours msonnxruntime-web msours / refverdict (bar 2.5, target 1.5)
minilm_fp32_b13.87.20.53target
minilm_fp32_b8109.31.08target
bert_fp32_b110.610.41.02target
bert_fp32_b838.626.81.44target
resnet50_fp32_b14.86.20.77target
resnet50_fp32_b821.6141.54met
mobilenet_fp32_b13.75.80.64target
mobilenet_fp32_b87.590.83target
dbnet_fp32_b15.29.30.56target
crnn_fp32_b13.221.20.15target
whisper_enc_b168.456.61.21target
whisper_dec_b122.317.71.26target

Windows, Intel Iris Xe (Windows 11, driver 101.7085), indicative only

Not publishable: one run on a shared laptop, ONNX Runtime 1.24.4 DirectML wheel, tools/bar.ps1. The float32 transformer rows (BERT, MiniLM), ResNet-50 (float32 and float16), MobileNetV3 at batch 8 and Whisper miss the 1.5 bar against DirectML (1.53 to 2.89): that GPU has no cooperative matrix, so the portable tiled kernels run. They ship as documented misses. NativeAOT on Windows is untested.

rowours msDirectML msours / DirectMLWebGPU EP msours / WebGPU EP
bert_fp32_b1116.2242.5432.73132.1370.88
bert_fp32_b8871.4301.2852.89577.9781.51
bert_int8_b147.61129.4020.37281.9940.17
crnn_fp32_b15.4118.9920.2881.5910.07
dbnet_fp32_b134.3227.2371.2641.9740.82
minilm_fp16_b121.0622.8410.9216.3711.29
minilm_fp32_b128.6410.9172.6219.6521.46
minilm_fp32_b8113.6345.3242.5192.671.23
minilm_int8_b115.723.650.6634.0990.46
mobilenet_fp32_b111.729.6251.2211.5161.02
mobilenet_fp32_b850.2332.5341.5442.671.18
mobilenet_int8_b116.7848.4830.35481.8710.03
resnet50_fp16_b179.6930.1072.6530.5482.61
resnet50_fp32_b151.1633.3641.5340.2451.27
resnet50_fp32_b8375.45141.5462.65216.9231.73
resnet50_int8_b163.3988.1770.72539.1530.12
whisper_dec_b1315.7139.0742.27203.8361.55
whisper_dec_int8_b1124.29312.9330.41135.4040.11
whisper_enc_b11843.84789.5232.341388.8691.33
whisper_enc_int8_b1960.421051.380.915388.2660.18

Correctness of the same runs

OneModel.Gpu.Tests (383 tests, 0 failed, 0 skipped): RTX 4070 and llvmpipe and RADV (Mesa 25.2.8) with the Khronos validation layer on, 0 validation messages; Apple M2 with Metal API and shader validation fatal. All 21 rows (20 above plus the greedy decode) with RequireGpu, fast and exact: 100 % of nodes in one region on every device, outputs identical between two runs in each mode (40 of 40 model-mode pairs per device), 0 validation messages. float32 rows are within a scaled error of 1.03e-5 of the CPU's exact mode on every device (Whisper-small encoder 8.0e-5), float16 within 1.2e-3, the 8-bit rows within the int8 policy (model-level error against the CPU exact mode 3.9e-4 to 8.8e-1, reported next to the CPU's own fast-versus-exact drift). CRNN greedy ids and the Whisper decoder's greedy tokens (8 of 8) equal the CPU's on every device. The Whisper-small encoder at batch 4 against a float64 evaluation, 16 inputs: mean error 1.14 (fast) and 1.21 (exact) times the CPU exact mode's on the RTX 4070 (max 0.90 and 0.97 times), 1.11 and 1.22 on the M2 (max 1.17 and 1.00), within 1.5 times the CPU exact mode's error. Chrome (RTX 4070): all rows fast and exact with RequireGpu, one region, identical runs, no page errors; SwiftShader subset (MiniLM, DBNet, CRNN, ResNet-50, Whisper decoder) likewise. OneModel.Tests 999 passed, 4 skipped, golden table equal to the base, NativeAOT smoke publish without trim or AOT warnings, run on RTX 4070 and llvmpipe with validation (all ConvInteger and model checks ok).