Rust: ThreadRng ์„ฑ๋Šฅ ๋ฒ„๊ทธ

์— ๋งŒ๋“  2017๋…„ 07์›” 08์ผ  ยท  3์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: rust-lang/rust

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 ... ๋ฒค์น˜: 49ns/iter(+/- 1)

๊ทธ๋Ÿฌ๋‚˜ JHM์—์„œ ๋™์ผํ•œ ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ:

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

๋‚ด ๋žฉํ†ฑ์—์„œ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋ฒค์น˜๋งˆํฌ ๋ชจ๋“œ Cnt ์ ์ˆ˜ ์˜ค๋ฅ˜ ๋‹จ์œ„
Main.testRnd ํ‰๊ท  20 9,018 ยฑ 0,094ns/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-nightly
LLVM ๋ฒ„์ „: 4.0

์ž๋ฐ”:
์˜คํ”ˆJDK 1.8.131

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

rand ๋Š” ์ž์ฒด ์ €์žฅ์†Œ๊ฐ€ ์žˆ๋Š” ์™ธ๋ถ€ ํฌ๋ ˆ์ดํŠธ์ด๋ฏ€๋กœ, ์ด๊ฒƒ์ด rand ์˜ ์ž˜๋ชป์ด ์•„๋‹ˆ๋ผ Rust์˜ ์ž˜๋ชป์ด๋ผ๋Š” ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ๋“  ์ž…์ฆํ•  ์ˆ˜ ์—†๋‹ค๋ฉด ์ด ๋ฌธ์ œ๋Š” ์•„๋งˆ๋„ ๊ฑฐ๊ธฐ ์— ์†ํ• 

๊ทธ๋Ÿฌ๋‚˜ ์ •๋ง๋กœ ๋ฌผ์–ด์•ผ ํ•  ์งˆ๋ฌธ์€ ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋‚œ์ˆ˜๋ฅผ ์–ป๋Š” ๊ฒƒ์ž…๋‹ˆ๊นŒ? rand::ThreadRng ๋Š” ์•”ํ˜ธํ™”๋œ ๋ณด์•ˆ RNG์ด๋ฏ€๋กœ ๋ณด์•ˆ์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ RNG์— ๊ณ ์œ ํ•œ ์„ฑ๋Šฅ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด... "ThreadLocalRandom์˜ ์ธ์Šคํ„ด์Šค๋Š” ์•”ํ˜ธํ•™์ ์œผ๋กœ ์•ˆ์ „ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. " ์ด๋Š” ๊ณต์ •ํ•œ ๋น„๊ต์กฐ์ฐจ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ž‘์„ฑ๋œ ๋Œ€๋กœ ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ 21ns/iter์ž…๋‹ˆ๋‹ค.

thread_rng() ์˜ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•˜๋„๋ก ๋ฒค์น˜๋งˆํฌ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด 15ns/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() ํ•˜๊ณ  ์•”ํ˜ธํ™” ๋ณด์•ˆ์„ ๋ฒ„๋ฆฌ๋ฉด 3ns/iter๋กœ ์•ž์„œ๊ฐ‘๋‹ˆ๋‹ค.

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

๋ชจ๋“  3 ๋Œ“๊ธ€

rand ๋Š” ์ž์ฒด ์ €์žฅ์†Œ๊ฐ€ ์žˆ๋Š” ์™ธ๋ถ€ ํฌ๋ ˆ์ดํŠธ์ด๋ฏ€๋กœ, ์ด๊ฒƒ์ด rand ์˜ ์ž˜๋ชป์ด ์•„๋‹ˆ๋ผ Rust์˜ ์ž˜๋ชป์ด๋ผ๋Š” ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ๋“  ์ž…์ฆํ•  ์ˆ˜ ์—†๋‹ค๋ฉด ์ด ๋ฌธ์ œ๋Š” ์•„๋งˆ๋„ ๊ฑฐ๊ธฐ ์— ์†ํ• 

๊ทธ๋Ÿฌ๋‚˜ ์ •๋ง๋กœ ๋ฌผ์–ด์•ผ ํ•  ์งˆ๋ฌธ์€ ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋‚œ์ˆ˜๋ฅผ ์–ป๋Š” ๊ฒƒ์ž…๋‹ˆ๊นŒ? rand::ThreadRng ๋Š” ์•”ํ˜ธํ™”๋œ ๋ณด์•ˆ RNG์ด๋ฏ€๋กœ ๋ณด์•ˆ์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ RNG์— ๊ณ ์œ ํ•œ ์„ฑ๋Šฅ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด... "ThreadLocalRandom์˜ ์ธ์Šคํ„ด์Šค๋Š” ์•”ํ˜ธํ•™์ ์œผ๋กœ ์•ˆ์ „ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. " ์ด๋Š” ๊ณต์ •ํ•œ ๋น„๊ต์กฐ์ฐจ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ž‘์„ฑ๋œ ๋Œ€๋กœ ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ 21ns/iter์ž…๋‹ˆ๋‹ค.

thread_rng() ์˜ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•˜๋„๋ก ๋ฒค์น˜๋งˆํฌ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด 15ns/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() ํ•˜๊ณ  ์•”ํ˜ธํ™” ๋ณด์•ˆ์„ ๋ฒ„๋ฆฌ๋ฉด 3ns/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(claimed-to-be) ์•”ํ˜ธํ•™์ ์œผ๋กœ ์•ˆ์ „ํ•œ PRNG ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ

๋งŽ์€ ์„ค๋ช… ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰