gpt4 book ai didi

multithreading - 如何在Rust中的线程之间共享不可变数据?

转载 作者:行者123 更新时间:2023-12-03 11:35:25 24 4
gpt4 key购买 nike

我正在Rust中开发一种光线追踪器,作为一种学习语言的方法,单线程版本可以正常工作。我想通过多线程来加快它的速度,而在C/C++中对光线跟踪器进行多线程是相对容易的,因为大多数共享数据都是只读的(唯一的问题是在写入像素数据时发生的)。但是我在Rust及其所有权规则上遇到了更多麻烦。
我有一个特质Hittable: Send + Sync来表示世界上可能会碰到的不同类型的事物(球体,网格物体),并且我将SendSync的实现留空了,因为我实际上不需要它们。然后,我得到了一个类型为Vec<Box<dyn Hittable>>的世界对象的vec。对于实际的多线程,我正在尝试如下操作:

    let pixels_mutex: Arc<Mutex<Vec<Vec<(f64, f64, f64, u32)>>>> = Arc::new(Mutex::new(pixels));
let vec_arc: Arc<Vec<Box<dyn Hittable>>> = Arc::new(vec);

let mut thread_vec: Vec<thread::JoinHandle<()>> = Vec::new();

for _ in 0..NUM_THREADS {
let camera_clone = camera.clone();
thread_vec.push(thread::spawn(move || {
for r in 0..RAYS_PER_THREAD {
if r % THREAD_UPDATE == 0 {
println!("Thread drawing ray {} of {} ({:.2}%)", r, RAYS_PER_THREAD, (r as f64 * 100.) / (RAYS_PER_THREAD as f64));
}
let u: f64 = util::rand();
let v: f64 = util::rand();
let ray = camera_clone.get_ray(u, v);
let res = geometry::thread_safe_cast_ray(&ray, &vec_arc, MAX_DEPTH);
let i = (u * IMAGE_WIDTH as f64).floor() as usize;
let j = (v * IMAGE_HEIGHT as f64).floor() as usize;
util::thread_safe_increment_color(&pixels_mutex, j, i, &res);
}
}));
}

for handle in thread_vec {
handle.join().unwrap();
}
我已经实现了 thread_safe_increment_color,这看起来还不错,但是我一直在做 thread_safe_cast_ray,直到让此循环生效为止。我在这段代码中遇到的问题是每个线程都试图将 vec_arc移入其闭包中,这违反了所有权规则。我尝试像使用 vec_arc一样克隆 camera,但是编译器不允许我这样做,这是因为我的 Hittable特性不需要 CopyClone特性。我实现 Hittable的结构不能简单地使用 derive(Copy, Clone),因为它们包含 Box<dyn Material>,其中 Material是代表对象 Material 的另一个特征。
我以为这会容易得多,因为我知道大多数数据( pixels_mutex除外)都是只读的。我如何在正在创建的线程之间共享 vec_arc(和 pixels_mutex)?

最佳答案

您应该像使用相机一样克隆vec_arc。由于它是Arc,因此克隆很便宜,并且不需要Vec及其元素是可克隆的。您只需要确保克隆智能指针而不是向量,并使用关联的函数即可:

let vec_arc = Arc::clone(&vec_arc);
另一种选择是使用 scoped threads,在这种情况下,您根本不需要使用 Arc,您只需将闭包设置为非 move即可直接访问局部变量。您的代码将如下所示:
crossbeam::scope(|s| {
for _ in 0..NUM_THREADS {
let camera_clone = camera.clone();
thread_vec.push(s.spawn(|_| {
// your code here, using `vec` directly instead of `vec_arc`
...
}).unwrap());
}
}).unwrap(); // here threads are joined automatically

关于multithreading - 如何在Rust中的线程之间共享不可变数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62744175/

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