I have written rather a lot of code to test this on two machines, the first of which is a Windows machine that has an Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz processor. I am using a recent MinGW compiler via the CodeBlocks IDE, with optimizations set at O3 and expensive_optimizations enabled, but no chip-specific optimizations.
I have run the same code on an Intel(R) Xeon CPU E5-2650L v4 @ 1.70GHz processor, Ubuntu OS, and GCC 7.5 compiler, with the same compiler options.
I am using the pcg32 random number generator to generate the required uniform variates inside the code helpfully provided by @Alex. pcg32 is extremely fast - my implementation, copied from who knows where, takes only 18% longer than the C library rand()
function while returning an unsigned integer between 0 and 4294967296$ = 2^{32}$, whereas rand()
returns a signed integer between 0 and 32767 (much poorer granularity), and has excellent properties. See https://www.pcg-random.org/ for more.
Fast Windows machine:
Generating 10 million variates using the pcg32 version of the code that R uses took 568,095 microseconds, including the overhead induced by the for
loop.
Generating 10 million variates using the inverse probability transform took 527,346 microseconds, including the overhead induced by the for
loop. This is roughly 93% of the time that the A-D algorithm uses. Roughly 40% of the time for the inverse probability transform algorithm appears to be loop overhead and the uniform RNG.
Slower Linux machine: the A-D algorithm took 666,358 microseconds, the inverse probability transform took only 555,192 microseconds. This is roughly 83% of the time that the A-D algorithm uses.
These results certainly validate the OP's suspicion that things may have changed since the 1970s. Regardless of the algorithm choice, being able to generate 15-20 million exponential random numbers in one second on one thread is certainly a nice capability to have!
One interesting finding is that the runtimes don't scale with the CPU speed; they are a little greater on the Linux box than on the Windows box, but not nearly the 2x+ difference in speed. Of course, the compilers are different, and GHz is by no means the sole influence on runtime.
I'd be happy to post the code, but there's about 130 lines of it, including some comments and blank lines. Thoughts?
R
for the answer? On my system, the log-uniform method is 60+% slower.with(data.frame(n = 1e8, lambda = pi), { print(system.time(x <- rexp(n, 1/lambda))); print(system.time(x <- -log(runif(n)) * lambda)) })
$\endgroup$