Diese Frage bezieht sich in erster Linie auf ein praktisches Software-Engineering-Problem, aber ich wäre gespannt, ob Theoretiker weitere Einblicke in dieses Problem gewähren könnten.
Einfach gesagt, ich habe eine Monte-Carlo-Simulation, die einen Pseudozufallszahlengenerator verwendet, und ich möchte sie parallelisieren, damit 1000 Computer dieselbe Simulation parallel ausführen. Deshalb brauche ich 1000 unabhängige Ströme von Pseudozufallszahlen.
Können wir 1000 parallele Streams mit den folgenden Eigenschaften haben? Hier sollte ein sehr bekanntes und weit verbreitetes PRNG mit allen Arten von guten theoretischen und empirischen Eigenschaften sein.
Die Streams sind nachweislich so gut wie das, was ich bekommen würde, wenn ich einfach und den von erzeugten Stream in 1000 Streams aufteilen würde .
Erzeugen die nächste Nummer in jedem Stream ist (fast) so schnell wie die nächste Nummer mit der Erzeugung .
Anders ausgedrückt: Können wir mehrere unabhängige Streams "kostenlos" erhalten?
Wenn wir einfach , immer 999 Zahlen verwerfen und 1 auswählen, dann hätten wir natürlich Eigenschaft 1, aber wir würden in der Laufzeit um den Faktor 1000 verlieren.
Eine einfache Idee wäre, 1000 Kopien von mit den Startwerten 1, 2, ..., 1000 zu verwenden. Dies wäre sicherlich schnell, aber es ist nicht offensichtlich, ob die Streams gute statistische Eigenschaften haben.
Nach einigem googeln habe ich zum Beispiel folgendes gefunden:
Die SPRNG- Bibliothek scheint genau für diesen Zweck konzipiert zu sein und unterstützt mehrere PRNGs .
Mersenne Twister scheint heutzutage ein beliebtes PRNG zu sein, und ich habe einige Hinweise auf eine Variante gefunden, die mehrere Streams gleichzeitig erzeugen kann.
Aber all dies ist so weit von meinen eigenen Forschungsgebieten entfernt, dass ich nicht herausfinden konnte, was wirklich auf dem neuesten Stand ist und welche Konstruktionen nicht nur in der Theorie, sondern auch in der Praxis gut funktionieren.
Einige Erläuterungen: Ich benötige keinerlei kryptografische Eigenschaften. Dies ist für die wissenschaftliche Berechnung. Ich brauche Milliarden von Zufallszahlen, damit wir jeden Generator mit einer Periode von vergessen können .
Bearbeiten: Ich kann kein echtes RNG verwenden. Ich brauche einen deterministischen PRNG. Erstens hilft es sehr beim Debuggen und macht alles wiederholbar. Zweitens ermöglicht es mir, z. B. das Median-Finden sehr effizient durchzuführen, indem ich die Tatsache ausnutze, dass ich das Multi-Pass-Modell verwenden kann (siehe diese Frage ).
Bearbeiten 2: Es gibt eine eng verwandte Frage @ StackOverflow: Pseudo-Zufallszahlengenerator für Cluster-Umgebung .
quelle
Antworten:
Sie können eine Weiterentwicklung des von Saito und Matsumoto entwickelten Mersenne Twister-Algorithmus verwenden:
SIMD-orientierter Fast Mersenne Twister (SFMT)
SFMT ist ein LFSR-Generator (Linear Feedbacked Shift Register), der in einem Schritt eine 128-Bit-Pseudozufallszahl generiert. SFMT wurde mit der neuesten Parallelität moderner CPUs entwickelt, beispielsweise mit mehrstufigen Pipelining- und SIMD-Befehlen (z. B. 128-Bit-Integer-Befehle). Es unterstützt 32-Bit- und 64-Bit-Ganzzahlen sowie Gleitkommazahlen mit doppelter Genauigkeit als Ausgabe. SFMT ist auf den meisten Plattformen viel schneller als MT. Nicht nur die Geschwindigkeit, sondern auch die Dimensionen von Gleichverteilungen mit v-Bit-Genauigkeit werden verbessert. Darüber hinaus ist die Wiederherstellung von einem Nullüberschuss-Anfangszustand viel schneller. Siehe Masterarbeit von Mutsuo Saito für Details .
Der Zeitraum variiert zwischen und 2 216091 - 1 .2607- 1 2216091- 1
Die Verwendung desselben Pesudorandom-Zahlengenerators zum Erzeugen mehrerer unabhängiger Datenströme durch Ändern der Anfangswerte kann ein Problem verursachen (mit vernachlässigbar geringer Wahrscheinlichkeit). Um das Problem zu vermeiden, wird die Verwendung unterschiedlicher Parameter für jede Generation bevorzugt. Diese Technik wird als dynamische Erstellung der MT-Parameter bezeichnet.
Im SFMT-Quellcode finden Sie einige Beispiele für Parametersätze (variabler Perioden) und ein awk-Skript zum Konvertieren einer CSV-Datei in einen kompilierbaren Parametersatz. Es gibt auch ein Tool namens " Dynamische Erstellung von Mersenne Twister-Generatoren ".
Die Autoren haben kürzlich eine andere modifizierte Version des Mersenne Twister entwickelt - Mersenne Twister für Grafikprozessoren -, die für die Ausführung in GPUs und die Nutzung ihrer nativen parallelen Ausführungsthreads ausgelegt ist. Das Hauptmerkmal ist die Geschwindigkeit: zufällige Ganzzahlen alle 4,6 ms auf einer GeForce GTX 260.5 × 107
Die Perioden der generierten Sequenz sind , 2 23209 - 1 und 2 44497 - 1 für die 32-Bit-Version und 2 23209 - 1 , 2 44497 - 1 , 2 110503 - 1 für die 64-Bit-Version. Es unterstützt 128 Parametersätze für jede Periode, mit anderen Worten, es kann 128 unabhängige Pseudozufallszahlensequenzen für jede Periode erzeugen. Wir haben Dynamic Creator für MTGP entwickelt, das mehr Parametersätze generiert211213- 1 223209- 1 244497- 1 223209- 1 244497- 1 2110503- 1
In der Tat bieten sie ein MTGPDC-Tool zum Erstellen von bis zu Parametersätzen (dh unabhängigen Streams).232
Der Algorithmus besteht die wichtigsten Zufallstests wie Diehard und NIST.
Ein vorläufiges Papier ist auch für arXiv erhältlich: Eine Variante von Mersenne Twister, die für Grafikprozessoren geeignet ist
quelle
Es scheint viele Möglichkeiten zu geben, um dieses Problem anzugehen, aber eine einfache Möglichkeit wäre die Verwendung des Blum Blum Shub PRNG. Dieses PRNG wird durch die Wiederholungsrelation , wobei N ein Semiprime ist. Um ein zufälliges Bit daraus zu ziehen, können Sie einfach die Bitparität von x i nehmen . Das Schöne daran ist, dass x i + k = x 2 k i mod N = x 2 k mod λ ( N ) i istxi+1=x2i mod N N xi Sie können direkt jeden Schritt in der Zeitkonstante in k (dh O ( log ( N ) 3 ) oder schneller berechnen, je nachdem, welchen Multiplikationsalgorithmus Sie für das modulare Exponential verwenden. Wenn Sie also M Maschinen haben, können Sie für die von y indizierte Maschineden Generator x i + 1 verwenden , y = x 2 M mod λ ( N ) i mod N , wobei x 0 , y = xxi+k=x2ki mod N=x2k mod λ(N)imod N k O(log(N)3) M y xi+1,y=x2Mmod λ(N)i mod N x0,y=x2y mod λ(N)0 mod N x0
This isn't the fastest of PRNGs, though, so it will only be useful if the overhead of whatever you are doing in the simulation is significantly more than the cost of the PRNG. However it is worth pointing out that it will be much faster for certain combinations ofM and N than others, particularly if the binary representation of 2M mod λ(N) contains few 1s or is small.
quelle
How about a preprocessing phase? Given a random seeds (of size n ), run X to get a pseudorandom stream of size 1000n . Denote this stream by s1,s2,…,s1000 , where for 1≤i≤1000 , si is a contiguous portion of the stream of size n .
This preprocessing phase can be done with a very low overhead, given the fact thatX is an efficient PRNG (today, we have very fast PRNG's).
Now, givesi as the seed to the i th machine, which uses X to generate its own pseudorandom stream.
Given the nice properties ofX , unless s is known, for any 1≤i<j≤1000 , the seeds si and sj are computationally independent. Moreover, you only have to generate and save one small seed (i.e. s ); therefore, this approach does not need a great deal of true randomness or storage.
quelle
You could use a pseudorandom functionf such as AES or ChaCha with a single random key, encrypting a counter. Assign each of the M=1000 parallel processes a unique starting value in {0,1,…,M−1} , and then compute the j th random block of bits for process i as f(i+jM) , i.e. increment the counter in each process by M for every subsequent block of random bits.
This will give you a cryptographic RNG on every process, but it does not necessarily come with a performance cost. AES is fast if you have hardware that supports it, and ChaCha is fast regardless. Of course, you'll want to measure this in your specific setting to be sure.
Both desired properties 1 and 2 are directly satisfied by this. It's moreover convenient that the behavior of the entire system of parallel tasks is controlled by a single "seed" (the key forf ).
quelle
There is now a jump function for SFMT (a fast Mersenne Twister implementation).
This allows me to initialise 1000 MTs so that there is no cycle overlap. And SFMT should be faster than MTGP. Almost perfect for my purposes.
quelle
You can just use 1000 instances of the Mersenne Twister initialized with different seeds.
You can sample the seeds from another Mersenne Twister, or, to be surer of their independence, from the OS cryptographic pseudorandom number generator (/dev/urandom in Linux).
The Mersenne Twister always operates on the same cyclic sequence, the seed controls where you start generating it. With indepenently sampled seeds, each generator will start at different, typically very far points, with a very small probability of intersection.
quelle