Now I have some numbers.
I used `timer:tc/3 on:
lcg33_bare(Range, Seed, N) →
lcg33_bare(Range, Seed, N, 0).
lcg33_bare(_Range, _R, 0, V) →
V;
lcg33_bare(Range, R, N, V) →
{V1, R1} = lcg33_uniform(Range, R),
lcg33_bare(Range, R1, N-1, V bxor V1).
vs.
rand(Alg, Range, Seed, N) →
S = rand:seed_s(Alg, Seed),
rand_loop(Range, S, N, 0).
rand_loop(_Range, _S, 0, V) →
V;
rand_loop(Range, S, N, V) →
{V1, S1} = rand:uniform_s(Range, S),
rand_loop(Range, S1, N-1, V bxor V1).
Where lcg33_uniform(Range, R)
is both inlined and implemented
in rand
as a plug-in.
A loop generating 10000000 numbers in the range 1…2^30 uses
about 40 ns for the inlined generator and 50 ns for the one
in rand
. So the overhead is about 10 ns or 20%.
The same for the mlcg31 generator which is noticabely slower
gives an overhead of about 15 ns or 25%.
For a range that is not a power of 2 the difference between
the LCG and the MLCG generater is smaller and the overhead
for the LCG generator increases a bit, but all in all
seems to be around 10…15 ns or 20…25%. I guess this
is due to increased rejection sampling to satisfy the
range. This is probably also the reason the MLCG generator
has got a higher overhead for the 2^30 range since it
almost always has to do rejection sampling.
I would say that the overhead is worth the flexibility…