gpt4 book ai didi

multithreading - 如何在 Rust 中为不同线程克隆随机数生成器?

转载 作者:行者123 更新时间:2023-12-03 11:29:36 28 4
gpt4 key购买 nike

我正在研究基于 C++ 代码库(PBRT,如果有人熟悉的话)的光线追踪器的 Rust 实现。 C++ 版本定义的类之一是一系列采样器,以减少渲染图像中的噪声。在渲染过程中,只要需要随机数,就会将此采样器克隆到每个渲染线程中。这就是我在 Rust 中选择的方式,我承认这有点令人费解:

#[derive(Clone)]
pub struct PixelSampler {
samples_1d: Vec<Vec<f64>>,
samples_2d: Vec<Vec<Point2<f64>>>,
current_1d_dimension: i32,
current_2d_dimension: i32,
rng: rngs::ThreadRng
}
pub enum Samplers {
StratifiedSampler {x_samples: i64, y_samples: i64, jitter_samples: bool, pixel: PixelSampler },
ZeroTwoSequenceSampler { pixel: PixelSampler }
}

impl Clone for Samplers {
fn clone(&self) -> Self {
match self {
Samplers::StratifiedSampler { x_samples, y_samples, jitter_samples, pixel } => {
Samplers::StratifiedSampler {x_samples: *x_samples,
y_samples: *y_samples,
jitter_samples: *jitter_samples,
pixel: pixel.clone() }
}
Samplers::ZeroTwoSequenceSampler { pixel } => { Samplers::ZeroTwoSequenceSampler{ pixel: pixel.clone() } }
}
}
}
然后我还有一个 Integrator其中有一个 Samplers变体字段。在我的主渲染循环中,我有以下为每个线程运行的循环:
for _ in 0..NUM_THREADS {
let int_clone = integrator.clone(); // integrator just contains a Samplers
thread_vec.push(thread::spawn(move || {
loop {
// do main rendering loop
}
}));
}
但是当我用这个编译时,我收到错误:
“特征 std::marker::Send 没有为 std::ptr::NonNull<rand::rngs::adapter::reseeding::ReseedingRng<rand_chacha::chacha::ChaCha20Core, rand_core::os::OsRng>> 实现”。
我的理解是因为我只将克隆版本移动到线程中,实现 Send没有必要。我究竟做错了什么?

最佳答案

thread_rng()文档说,它是:

[...]essentially just a reference to the PRNG in thread-local memory.


因此,通过克隆“rng”,您没有复制生成器及其状态(我认为这是您的意图),而是创建了线程本地 RNG 的新句柄。这个句柄不是故意的 Send因为它访问线程本地 RNG 而不锁定以提高效率。
如果你想让你的结构包含一个实际的 RNG,并克隆结构来复制它,你可以使用 StdRng 类型,这是推荐的、高效且安全的 RNG。要实例化它,请使用 SeedableRng 中的方法特征。例如:
#[derive(Clone)]
pub struct PixelSampler {
samples_1d: Vec<Vec<f64>>,
samples_2d: Vec<Vec<Point2<f64>>>,
current_1d_dimension: i32,
current_2d_dimension: i32,
rng: StdRng,
}
// ...

let sampler = Samplers::ZeroTwoSequenceSampler {
pixel: PixelSampler {
samples_1d: vec![],
samples_2d: vec![],
current_1d_dimension: 0,
current_2d_dimension: 0,
rng: SeedableRng::from_entropy(),
},
};
// compiles because StdRng is Send
std::thread::spawn(move || sampler).join().unwrap();
playground 中的完整示例.

关于multithreading - 如何在 Rust 中为不同线程克隆随机数生成器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65053037/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com