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 ... bench: 49 ns/iter (+/- 1)
但是如果我在 JHM 上运行相同的基准测试:
<strong i="12">@Benchmark</strong>
public double testRnd() {
return ThreadLocalRandom.current().nextDouble(2, 100);
}
在我的笔记本电脑上,结果是:
基准模式 Cnt 分数误差单位
Main.testRnd 平均 20 9,018 ± 0,094 ns/op
所以差异是 5.44 倍,看起来像性能错误。
锈:
红糖
rustc 1.20.0-nightly (c9bb93576 2017-06-24)
二进制:rustc
提交哈希:c9bb93576d4484edd1b3c40eb2aea0dfa0788851
提交日期:2017-06-24
主机:x86_64-unknown-linux-gnu
版本:每晚 1.20.0
LLVM 版本:4.0
爪哇:
OpenJDK 1.8.131
由于rand
是一个有自己存储库的外部 crate,这个问题可能属于那里,除非你能够以某种方式证明这是 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
是一个有自己存储库的外部 crate,这个问题可能属于那里,除非你能够以某种方式证明这是 Rust 的错,而不是rand
的错。但是,您真正应该问的问题是,您得到的是哪种随机数?
rand::ThreadRng
是一种加密安全的 RNG,因此对于不需要那么安全的 RNG,它将在性能上处于劣势。 查看文档...“ ThreadLocalRandom 的实例在加密方面不安全。”这意味着您甚至没有进行公平的比较。对我来说,按照所写的方式运行基准测试是 21ns/iter。
修改您的基准以缓存
thread_rng()
的结果,对我来说将其速度提高了 15 ns/iter。但是,如果我使用
weak_rng()
并放弃加密安全性,它会提前到 3 ns/iter。