Rust: Bug de desempenho ThreadRng

Criado em 8 jul. 2017  ·  3Comentários  ·  Fonte: rust-lang/rust

ThreadRng funciona 5 vezes mais devagar do que ThreadLocalRandom em Java.

Eu executo este benchmark no Rust:

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

No meu laptop, o resultado é:
testes de teste :: bench_rnd ... bench: 49 ns / iter (+/- 1)

Mas se eu executar o mesmo benchmark no JHM:

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

No meu laptop, o resultado é:
Unidades de erro de pontuação do Cnt do modo de benchmark
Main.testRnd avgt 20 9.018 ± 0,094 ns / op

Portanto, a diferença é de 5,44 vezes parece bug de desempenho.

Meta

Ferrugem:

rbose
rustc 1.20.0-nightly (c9bb93576 24-06-2017)
binário: rustc
commit-hash: c9bb93576d4484edd1b3c40eb2aea0dfa0788851
data de confirmação: 24-06-2017
host: x86_64-unknown-linux-gnu
lançamento: 1.20.0 noturno
LLVM versão: 4.0

Java:
OpenJDK 1.8.131

Comentários muito úteis

Visto que rand é uma caixa externa com seu próprio repositório, este problema provavelmente pertence , a menos que você seja capaz de demonstrar de alguma forma que isso é culpa do Rust, e não de rand .

No entanto, a pergunta que você realmente deveria fazer é: que tipo de números aleatórios você está recebendo? rand::ThreadRng é um RNG criptograficamente seguro, portanto, terá uma desvantagem de desempenho inerente aos RNGs que não precisam ser tão seguros. Olhando a documentação ... "Instâncias de ThreadLocalRandom não são criptograficamente seguras." O que significa que você nem mesmo está fazendo uma comparação justa.

Executar seu benchmark conforme escrito é 21 ns / iter para mim.

Modificar seu benchmark para armazenar em cache o resultado de thread_rng() acelera 15 ns / iter para mim.

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

Se eu usar weak_rng() no entanto e descartar a segurança criptográfica, ela avançará para 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));
}

Todos 3 comentários

Visto que rand é uma caixa externa com seu próprio repositório, este problema provavelmente pertence , a menos que você seja capaz de demonstrar de alguma forma que isso é culpa do Rust, e não de rand .

No entanto, a pergunta que você realmente deveria fazer é: que tipo de números aleatórios você está recebendo? rand::ThreadRng é um RNG criptograficamente seguro, portanto, terá uma desvantagem de desempenho inerente aos RNGs que não precisam ser tão seguros. Olhando a documentação ... "Instâncias de ThreadLocalRandom não são criptograficamente seguras." O que significa que você nem mesmo está fazendo uma comparação justa.

Executar seu benchmark conforme escrito é 21 ns / iter para mim.

Modificar seu benchmark para armazenar em cache o resultado de thread_rng() acelera 15 ns / iter para mim.

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

Se eu usar weak_rng() no entanto e descartar a segurança criptográfica, ela avançará para 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));
}

Observe também que de Java ThreadLocalRandom é extremamente simples PRNG congruência linear , enquanto o Rust rand 's thread_rng() baseia-se no ISAAC (reivindicou-a-ser) PRNG criptograficamente segura que é mais caro, portanto, este benchmark não é exatamente uma comparação maçã com maçã.

Muito obrigado pela explicação.

Esta página foi útil?
0 / 5 - 0 avaliações