samedi 8 février 2020

Which of

Suppose you want to use C++ <random> facilities in a practical program (for some definition of "practical" — the constraints here are kind of part of this question). You've got code roughly like this:

int main(int argc, char **argv) {
    int seed = get_user_provided_seed_value(argc, argv);
    if (seed == 0) seed = std::random_device()();
    ENGINE g(seed);  // TODO: proper seeding?
    go_on_and_use(g);
}

My question is, what type should you use for ENGINE?

  • I used to always say std::mt19937 because it was quick to type and had name recognition. But these days it seems like everyone's saying that the Mersenne Twister is very heavyweight and cache-unfriendly and doesn't even pass all the statistical tests that others do.

  • I'd like to say std::default_random_engine because it's the obvious "default." But I don't know if it varies from platform to platform, and I don't know if it's statistically any good.

  • Since everyone's on a 64-bit platform these days, should we at least be using std::mt19937_64 over std::mt19937?

  • I'd like to say pcg64 or xoroshiro128 because they seem well-respected and lightweight, but they don't exist in <random> at all.

  • I don't know anything about minstd_rand, minstd_rand0, ranlux24, knuth_b, etc. — surely they must be good for something?

Obviously there are some competing constraints here.

  • Strength of the engine. (<random> has no cryptographically strong PRNGs, but still, some of the standardized ones are "weaker" than others, right?)

  • sizeof the engine.

  • Speed of its operator().

  • Ease of seeding. mt19937 is notoriously hard to seed properly because it has so much state to initialize.

  • Portability between library vendors. If one vendor's foo_engine produces different numbers from another vendor's foo_engine, that's not good for some applications. (Hopefully this rules out nothing except maybe default_random_engine.)

Weighing all these constraints as best you can, what would you say is the ultimate "best-practice staying-within-the-standard-library" answer? Should I just keep using std::mt19937, or what?

Aucun commentaire:

Enregistrer un commentaire