ThreadRngは、JavaのThreadLocalRandomよりも5倍遅く動作します。
私はこのベンチマークをRustで実行します。
#[bench]
fn bench_rnd(b: &mut Bencher) {
b.iter(|| rand::thread_rng().gen_range::<f64>(2.0, 100.0));
}
私のラップトップでは、結果は次のとおりです。
テストテスト:: bench_rnd ...ベンチ:49 ns / iter(+/- 1)
しかし、JHMで同じベンチマークを実行すると、次のようになります。
<strong i="12">@Benchmark</strong>
public double testRnd() {
return ThreadLocalRandom.current().nextDouble(2, 100);
}
私のラップトップでは、結果は次のとおりです。
ベンチマークモードCntスコアエラー単位
Main.testRnd avgt 209,018±0,094ns / op
したがって、5.44倍の違いはパフォーマンスのバグのように見えます。
さび:
rbose
rustc 1.20.0-毎晩(c9bb93576 2017-06-24)
バイナリ:rustc
コミットハッシュ:c9bb93576d4484edd1b3c40eb2aea0dfa0788851
コミット日:2017-06-24
ホスト:x86_64-unknown-linux-gnu
リリース:1.20.0-毎晩
LLVMバージョン:4.0
Java:
OpenJDK 1.8.131
rand
は独自のリポジトリを持つ外部クレートであるため、これがRustのせいであり、 rand
のせいではないことを何らかの方法で証明できない限り、この問題はおそらくそこに属します。
しかし、あなたが本当に尋ねるべき質問は、あなたはどんな種類の乱数を手に入れているのかということです。 rand::ThreadRng
は暗号的に安全なRNGであるため、それほど安全である必要のないRNGに固有のパフォーマンス上の欠点があります。 ドキュメントを見ると...「ThreadLocalRandomのインスタンスは暗号的に安全ではありません。」これは、公正な比較さえ行っていないことを意味します。
書かれたとおりにベンチマークを実行することは、私にとって21ns / iterです。
thread_rng()
の結果をキャッシュするようにベンチマークを変更すると、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));
}
ただし、 weak_rng()
を使用して暗号化セキュリティを破棄すると、3 ns / iterまで競合します。
#[bench]
fn bench_rnd(b: &mut Bencher) {
let mut rng = rand::weak_rng();
b.iter(|| rng.gen_range::<f64>(2.0, 100.0));
}
また、JavaのThreadLocalRandom
は非常に単純な線形合同PRNGであり、Rustのrand
のthread_rng()
はISAAC(主張されている)の暗号的に安全なPRNGに基づいて
説明ありがとうございます。
最も参考になるコメント
rand
は独自のリポジトリを持つ外部クレートであるため、これがRustのせいであり、rand
のせいではないことを何らかの方法で証明できない限り、この問題はおそらくそこに属します。しかし、あなたが本当に尋ねるべき質問は、あなたはどんな種類の乱数を手に入れているのかということです。
rand::ThreadRng
は暗号的に安全なRNGであるため、それほど安全である必要のないRNGに固有のパフォーマンス上の欠点があります。 ドキュメントを見ると...「ThreadLocalRandomのインスタンスは暗号的に安全ではありません。」これは、公正な比較さえ行っていないことを意味します。書かれたとおりにベンチマークを実行することは、私にとって21ns / iterです。
thread_rng()
の結果をキャッシュするようにベンチマークを変更すると、15 ns / iter高速化されます。ただし、
weak_rng()
を使用して暗号化セキュリティを破棄すると、3 ns / iterまで競合します。