tandem rng tandem-ml GitHub

Performance

dune exec --release bench/bench.exe produces the figures. Every figure is GiB/s of output.

CPU

Apple M4, one core, OCaml 5.5.1 with flambda. Fills of 2^22 elements, best of five. A scalar draw counts the bytes of its value: 4 for a 32-bit draw, 8 for a Float64 draw. Each row has a Random.State (LXM) baseline that makes the same element type, a loop into an array of that type for the fills. The standard library has no normals or exponentials, so those rows compare against a Random.State.float loop.

Fill GiB/s Baseline loop GiB/s
fill_u32 19.24 Random.State.bits32 1.06
fill_float 16.66 Random.State.float 1. 2.09
Float_array.fill_float 16.66 Random.State.float 1. 2.14
fill_below32, range 1000 7.75 Random.State.int 1000 1.04
fill_normal 7.78 Random.State.float 1. 2.09
fill_exponential 6.07 Random.State.float 1. 2.09
Pure.fill_u32 1.94 Random.State.bits32 1.06
Pure.fill_float 1.97 Random.State.float 1. 2.09
Pure.fill_normal 1.03 Random.State.float 1. 2.09
Pure.fill_exponential 0.74 Random.State.float 1. 2.09
Scalar draw GiB/s Baseline GiB/s
Tandem.u32 2.09 Random.State.bits32 1.08
Tandem.float 3.57 Random.State.float 1. 2.13
Tandem.below32 1000 1.30 Random.State.int 1000 1.05
Tandem.normal 2.25 Random.State.float 1. 2.13
Tandem.State.bits 1.96 Random.State.bits (30 bits) 1.09
Tandem.State.bits64 3.69 Random.State.bits64 2.14
Tandem.State.float 1. 3.60 Random.State.float 1. 2.13
Tandem.State.int 1000 1.48 Random.State.int 1000 1.05

A value draw allocates its successor generator, four words. The State draws allocate nothing. Pure.fill_exponential spends most of its time in Float.fma, a C call in OCaml.