Ich versuche zu verstehen, wie die C++ 11 Zufallszahlengenerierungsfunktionen verwendet werden sollen. Mein Anliegen ist Leistung.Effiziente Zufallszahlengenerierung mit C++ 11 <random>
Angenommen, wir müssen eine Reihe von zufälligen Ganzzahlen zwischen 0..k
, aber k
ändert bei jedem Schritt. Was ist der beste Weg, um fortzufahren?
Beispiel:
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
std::uniform_int_distribution<> dist(0, k);
int random_number = dist(engine);
// do something with random number
}
Die Verteilungen, die die <random>
Header bietet, sind sehr bequem. Aber sie sind für den Benutzer undurchsichtig, so dass ich nicht leicht vorhersagen kann, wie sie funktionieren werden. Es ist zum Beispiel nicht klar, wie viel (wenn überhaupt) Laufzeit-Overhead durch die obige Konstruktion von dist
verursacht wird.
Stattdessen könnte ich so etwas wie
verwendet habenstd::uniform_real_distribution<> dist(0.0, 1.0);
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
int random_number = std::floor((k+1)*dist(engine));
// do something with random number
}
, die in jeder Iteration ein neues Objekt vermeidet zu konstruieren.
Zufallszahlen werden oft in numerischen Simulationen verwendet, bei denen die Leistung wichtig ist. Was ist der beste Weg, um <random>
in diesen Situationen zu verwenden?
Bitte antworten Sie nicht "Profil es". Profiling ist Teil einer effektiven Optimierung, aber auch ein gutes Verständnis davon, wie eine Bibliothek verwendet werden soll, und die Leistungsmerkmale dieser Bibliothek. Wenn die Antwort ist, dass es von der Standard-Bibliothek-Implementierung abhängt, oder dass der einzige Weg zu wissen ist, es zu profilieren, dann würde ich lieber nicht die Verteilungen von <random>
überhaupt verwenden. Stattdessen kann ich meine eigene Implementierung verwenden, die für mich transparent ist und bei Bedarf viel einfacher zu optimieren ist.
Eine zusätzliche Überlegung: Eines der schönen Dinge über Generatoren wie 'std :: mt19937' ist, dass sie tragbar sind und die Implementierung * vom Standard vorgeschrieben ist. Die Verwendung des Generators mit einem gegebenen Startwert muss die gleiche Zufallsfolge von "uint32_t" für jede konforme Implementierung erzeugen.Die Verteilungsadapter 'std :: uniform_int_distribution' haben diese Garantie jedoch nicht. Wenn Sie sie verwenden, erhalten Sie möglicherweise eine andere Sequenz von Ints aus dem gleichen Seed, wenn Sie Compiler oder etwas ändern. Dies könnte eine Überlegung für numerische Simulationen sein. –
@ChrisBeck Ich wusste das nicht, danke für den Hinweis! – Szabolcs