Rust: ThreadRng-Leistungsfehler

Erstellt am 8. Juli 2017  ·  3Kommentare  ·  Quelle: rust-lang/rust

ThreadRng arbeitet fünfmal langsamer als ThreadLocalRandom in Java.

Ich führe diesen Benchmark in Rust aus:

#[bench]
fn bench_rnd(b: &mut Bencher) {
    b.iter(|| rand::thread_rng().gen_range::<f64>(2.0, 100.0));
}

Auf meinem Laptop ist das Ergebnis:
test tests::bench_rnd ... Bench: 49 ns/iter (+/- 1)

Aber wenn ich den gleichen Benchmark auf JHM ausführe:

<strong i="12">@Benchmark</strong>
public double testRnd() {
    return ThreadLocalRandom.current().nextDouble(2, 100);
}

Auf meinem Laptop ist das Ergebnis:
Benchmark-Modus Cnt Score Fehlereinheiten
Main.testRnd avgt 20 9.018 ± 0,094 ns/op

Der Unterschied ist also 5,44 mal, sieht nach einem Leistungsfehler aus.

Meta

Rost:

rbose
rustc 1.20.0-nächtlich (c9bb93576 2017-06-24)
binär: rost
Commit-Hash: c9bb93576d4484edd1b3c40eb2aea0dfa0788851
Zusagedatum: 2017-06-24
host: x86_64-unknown-linux-gnu
Release: 1.20.0-nächtlich
LLVM-Version: 4.0

Java:
OpenJDK 1.8.131

Hilfreichster Kommentar

Da rand eine externe Kiste mit eigenem Repository ist, gehört dieses Problem wahrscheinlich dorthin , es sei denn, Sie können irgendwie nachweisen, dass dies die Schuld von Rust ist und nicht die Schuld von rand .

Die Frage, die Sie sich jedoch wirklich stellen sollten, lautet: Welche Art von Zufallszahlen erhalten Sie? rand::ThreadRng ist ein kryptographisch sicherer RNG, daher wird er einen inhärenten Leistungsnachteil gegenüber RNGs haben, die nicht so sicher sein müssen. Wenn Sie sich die Dokumentation ansehen ... "Instanzen von ThreadLocalRandom sind nicht kryptographisch sicher." Das bedeutet, dass Sie nicht einmal einen fairen Vergleich anstellen.

Das Ausführen Ihres Benchmarks wie geschrieben ist für mich 21 ns / iter.

Das Ändern Ihres Benchmarks, um das Ergebnis von thread_rng() beschleunigt es für mich um 15 ns/Iter.

#[bench]
fn bench_rnd(b: &mut Bencher) {
    let mut rng = rand::thread_rng();
    b.iter(|| rng.gen_range::<f64>(2.0, 100.0));
}

Wenn ich jedoch weak_rng() und die kryptografische Sicherheit wegwerfe, rast es auf 3 ns/iter vor.

#[bench]
fn bench_rnd(b: &mut Bencher) {
    let mut rng = rand::weak_rng();
    b.iter(|| rng.gen_range::<f64>(2.0, 100.0));
}

Alle 3 Kommentare

Da rand eine externe Kiste mit eigenem Repository ist, gehört dieses Problem wahrscheinlich dorthin , es sei denn, Sie können irgendwie nachweisen, dass dies die Schuld von Rust ist und nicht die Schuld von rand .

Die Frage, die Sie sich jedoch wirklich stellen sollten, lautet: Welche Art von Zufallszahlen erhalten Sie? rand::ThreadRng ist ein kryptographisch sicherer RNG, daher wird er einen inhärenten Leistungsnachteil gegenüber RNGs haben, die nicht so sicher sein müssen. Wenn Sie sich die Dokumentation ansehen ... "Instanzen von ThreadLocalRandom sind nicht kryptographisch sicher." Das bedeutet, dass Sie nicht einmal einen fairen Vergleich anstellen.

Das Ausführen Ihres Benchmarks wie geschrieben ist für mich 21 ns / iter.

Das Ändern Ihres Benchmarks, um das Ergebnis von thread_rng() beschleunigt es für mich um 15 ns/Iter.

#[bench]
fn bench_rnd(b: &mut Bencher) {
    let mut rng = rand::thread_rng();
    b.iter(|| rng.gen_range::<f64>(2.0, 100.0));
}

Wenn ich jedoch weak_rng() und die kryptografische Sicherheit wegwerfe, rast es auf 3 ns/iter vor.

#[bench]
fn bench_rnd(b: &mut Bencher) {
    let mut rng = rand::weak_rng();
    b.iter(|| rng.gen_range::<f64>(2.0, 100.0));
}

Beachten Sie auch, dass ThreadLocalRandom Java ein extrem einfaches lineares kongruentes PRNG ist , während rand thread_rng() Rust auf dem kryptographisch sicheren PRNG von ISAAC (angeblich) basiert, das teurer ist, daher ist dieser Benchmark kein exakter Apfel-zu-Apfel-Vergleich.

Vielen Dank für die Erklärung.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen