Schneller real bewerteter Zufallsgenerator in Java

7

java.util.Random.nextDouble () ist langsam für mich und ich brauche etwas sehr schnelles.

Ich habe einige Google-Suche gemacht und ich habe nur Integer-basierte schnelle Zufallsgeneratoren gefunden. Ist hier irgendwas für reelle Zahlen aus Intervall & lt; 0, 1)?

    
Snurka Bill 22.03.2015, 10:41
quelle

6 Antworten

17

Wenn Sie etwas schnell brauchen und Zugriff auf Java8 haben, kann ich Ihnen java.utils SplitableRandom . Es ist schneller (~ doppelt so schnell) und hat eine bessere statistische Verteilung.

Wenn Sie einen noch schnelleren oder besseren Algorithmus benötigen, kann ich eine dieser spezialisierten XorShift-Varianten empfehlen:

Informationen zu diesen Algorithmen und ihrer Qualität finden Sie in diesem großen PRNG-Vergleich .

Ich habe einen unabhängigen Leistungsvergleich durchgeführt. Sie können die detaillierten Ergebnisse und den Code hier finden: github.com/tobijdc/PRNG-Performance

TLDR

Benutze niemals java.util.Random , benutze java.util.SplittableRandom . Wenn Sie schneller oder besser PRNG benötigen, verwenden Sie eine XorShift-Variante.

    
tobijdc 01.05.2015, 21:45
quelle
3

Sie könnten eine auf ganzzahligen Zahlen basierende Zufallszahl so ändern, dass sie im Intervall [0,1] wie folgt verdoppelt:

%Vor%

Wenn randInt () jedoch eine 32-Bit-Ganzzahl erzeugt, füllt dies nicht alle Bits des Doppelworts, weil das Doppelte 53 Mantissenbits hat. Sie könnten natürlich zwei zufällige Ganzzahlen erzeugen, um alle Mantissenbits zu füllen. Oder Sie können sich den Quellcode der Ramdom.nextDouble () Implementierung ansehen. Es verwendet fast sicher eine Ganzzahl RNG und wandelt einfach die Ausgabe in eine Doppel.

Was die Leistung angeht, sind die leistungsstärksten Zufallszahlengeneratoren lineare Kongruenzgeneratoren. Von diesen empfehle ich den Generator für numerische Rezepte. Sie können mehr Informationen über LCGs von Wikipedia sehen: Ссылка

Wenn Sie jedoch eine gute Zufälligkeit wünschen und die Leistung nicht so wichtig ist, denke ich Mersenne Twister ist die beste Wahl. Es hat auch eine Wikipedia-Seite: Ссылка

Es gibt einen neuen Zufallszahlengenerator namens PCG, der in Ссылка erklärt wird. Dies ist im Wesentlichen ein Nachbearbeitungsschritt für LCG, der die Zufälligkeit der LCG-Ausgabe verbessert. Beachten Sie, dass PCG langsamer als LCG ist, weil es einfach ein Nachbearbeitungsschritt für LCG ist. Wenn also die Leistung sehr wichtig ist und die Zufälligkeit nicht so wichtig ist, möchten Sie LCG statt PCG verwenden.

Beachten Sie, dass keiner der genannten Generatoren kryptographisch sicher ist. Wenn Sie die Werte für kryptografische Anwendungen verwenden müssen, sollten Sie einen kryptografisch sicheren Algorithmus verwenden. Ich glaube jedoch nicht, dass Dubletten für die Kryptographie verwendet werden würden.

    
juhist 22.03.2015 11:55
quelle
2

Beachten Sie, dass all diese Lösungen eine fundamentale Tatsache übersehen (die mir vor ein paar Wochen noch nicht bewusst war): Der Übergang von 64 Bit zu einem Doppelten mit einer Multiplikation ist ein großer Zeitverlust. Die Implementierung von xorshift128 + und xorshift1024 + in den DSI-Dienstprogrammen ( Ссылка ) verwendet direkte Bitmanipulation und die Ergebnisse sind beeindruckend.

Siehe die Benchmarks für nextDouble () bei

Ссылка

und die Qualität berichtet bei

Ссылка

    
seba 20.12.2015 17:58
quelle
1

Sie könnten ein Array von zufälligen Doppelpunkten erstellen, wenn Sie Ihr Programm starten und es dann einfach wiederholen. Dies ist viel schneller, aber die zufälligen Werte wiederholen sich selbst.

    
Alexanus 22.03.2015 11:36
quelle
1

Imho sollten Sie juhists Antwort nur akzeptieren - hier ist der Grund.

nextDouble ist langsam, weil es zwei Aufrufe von next () aufruft - es steht genau dort in der Dokumentation.

Ihre besten Optionen sind also:

  • Verwenden Sie einen schnellen 64-Bit-Generator, konvertieren Sie diesen zu Double (MT, PCG, xorshift *, ISAAC64, ...)
  • erzeugt direkt Doubles

Hier ist ein überlanger Benchmark mit Java's Random, einer LCG (so schlecht wie java.util.Random) und Marsaglias Universalgenerator (die Version, die Doubles erzeugt).

%Vor%     
loreb 25.03.2015 16:59
quelle
-1

Haben Sie tatsächlich Benchmarking oder Profiling durchgeführt, um zu zeigen, dass nextDouble der Flaschenhals ist? Haben Sie Alternativen wie MersenneTwister Streams-Bibliothek ? Ich schlage vor, diejenigen mit Benchmarking zu versuchen, aber es gibt kein kostenloses Mittagessen. Verbesserungen bei der Geschwindigkeit werden wahrscheinlich zu Lasten der Qualität gehen und umgekehrt.

    
pjs 22.03.2015 19:06
quelle