[Bench!][Mir] +54%..+185% performance boost for Mersenne Twister.

Joseph Rushton Wakeling via Digitalmars-d digitalmars-d at puremagic.com
Tue Dec 13 10:15:25 PST 2016


On Saturday, 26 November 2016 at 20:13:36 UTC, Andrei 
Alexandrescu wrote:
> Congrats! Also thanks for using the Boost license which would 
> allow backporting the improvements to Phobos. Who'd be up for 
> it?

I've finally found a moment to look into this (I'm at home 
recovering from a seasonal virus, which ironically puts some time 
and mental space in my hands).

It makes for an interesting comparison.  The traditional Mersenne 
Twister algorithm generates N random words in one go, and then 
iterates over them, before generating another N random words, and 
so on.  (Word == unsigned integer type.)

By contrast Ilya's implementation just updates the single next 
entry in the static array that stores the state of the engine.  
This would seem to work out cheaper on average: perhaps because 
the update-a-variate code stays hotter, perhaps because it 
involves less branching and looping.  It certainly makes for a 
simpler, easier to follow update.

However, it might be a good idea to benchmark this in a context 
where there are a lot of random variates being generated, but 
where other things are also happening that might render the 
update code less "hot" than a straightforward `foreach` loop 
benchmark.  (Maybe try it out with a Monte Carlo simulation ...?) 
  The tradeoff between many cheap updates and one expensive one, 
versus all updates being a little more expensive but less on 
average, might not be viable in some practical use-cases.

The Phobos implementation also includes a check on whether the 
generator is properly seeded, which is performed in every 
`popFront()`, which has a reasonably significant impact.  Ilya's 
implementation can get away with not performing that check 
because it uses `@disable this();` to remove the possibility of 
initializing the generator without it being properly seeded.  The 
impact of that check can possibly be lessened by making it a 
boolean comparison rather than the existing `size_t` equality 
comparison.

   -- action item here: could we deprecate `this()` in Phobos as a 
precursor to removing
      the opportunity to instantiate a generator without properly 
initializing it?

I'm going to try to put together a range-based version to see if 
this also makes any difference.  I'll post some benchmarks of my 
own once that's done, and if all looks good I'll try to put a 
Phobos PR together.

A few questions -- not blockers, but nice to understand:

   * @Ilya, is this implementation your own design, or do you have 
a reference
     for the rationale behind this revised implementation of MT?

   * Is there a particular reason why the `index` variable is a 
`Uint` (i.e.
     the word type of the generator) rather than a `size_t`?  I 
presume there's
     a motivation, since the casting back and forth in `opCall` 
would otherwise
     seem inconvenient.

   * Is there a motivation for the reverse iteration through the 
RNG state array?


More information about the Digitalmars-d mailing list