Multithreading Rust中大内存块的并行初始化
最好的方法是什么: 我有一个2GB内存块,需要用一些数据初始化。 数据都是独立的,因此我可以很容易地生成n个线程来初始化数据,每个线程在单独的内存位置上并行工作 我怎样才能“告诉”这个生锈。它不允许我在线程之间共享内存(这是有充分理由的,也是理所当然的)。我知道不会有竞争条件,因为每个线程在完全不同的内存位置上工作Multithreading Rust中大内存块的并行初始化,multithreading,rust,Multithreading,Rust,最好的方法是什么: 我有一个2GB内存块,需要用一些数据初始化。 数据都是独立的,因此我可以很容易地生成n个线程来初始化数据,每个线程在单独的内存位置上并行工作 我怎样才能“告诉”这个生锈。它不允许我在线程之间共享内存(这是有充分理由的,也是理所当然的)。我知道不会有竞争条件,因为每个线程在完全不同的内存位置上工作 一个想法是使用(横梁)通道。每个线程将计算发送到一个写入程序,该写入程序将内存放入正确的位置。唉,这感觉过于复杂,效率不够。是否有一些方法可以对线程的内存进行分区,以确保使用不同的线
一个想法是使用(横梁)通道。每个线程将计算发送到一个写入程序,该写入程序将内存放入正确的位置。唉,这感觉过于复杂,效率不够。是否有一些方法可以对线程的内存进行分区,以确保使用不同的线程进行操作时安全?并行性的go-to板条箱是,这可以简化:
use rayon::prelude::*;
// this just takes a big zeroed buffer and fills it with 1s with 10 threads
fn main() {
let mut data = vec![0u8; 2000000]; // pretend this is 2 GiB
data.chunks_mut(200000) // pretend this is 2 GiB / N threads
.par_bridge()
.for_each(|d| d.fill(1));
}
用于切片的
chunks\u mut()
函数已经可以为您提供许多可变切片,以分离原始图像的各个区域。然后,只需使用par_bridge()
将其转换为并行迭代器。并行化的目标是,这可以简化:
use rayon::prelude::*;
// this just takes a big zeroed buffer and fills it with 1s with 10 threads
fn main() {
let mut data = vec![0u8; 2000000]; // pretend this is 2 GiB
data.chunks_mut(200000) // pretend this is 2 GiB / N threads
.par_bridge()
.for_each(|d| d.fill(1));
}
用于切片的
chunks\u mut()
函数已经可以为您提供许多可变切片,以分离原始图像的各个区域。然后,只需使用par_bridge()
将其转换为并行迭代器。除了kmdreko推荐的优秀人造丝板条箱之外,还有一个更低级的原语,可以实现您想要的。您可以使用它将现有可变切片拆分为多个可变切片,而无需使用不安全代码:
let mut data = vec![0u8; 2_000_000]; // pretend this is 2 GiB
let mut data = &mut data[..];
let chunk_size = data.len() / n_threads;
for _ in 0..n_threads {
let (chunk, rest) = data.split_at_mut(chunk_size);
data = rest;
spawn(move |_| {
chunk.fill(1);
});
}
但是,要使其工作,您需要作用域线程,即允许引用借用值的线程。(这是合理的,因为作用域线程会自动连接所有创建的线程,从而确保没有线程比借用的值更长寿。)
下面是一个例子,使用与kmdreko的回答类似的设置:
use crossbeam_utils::thread;
fn main() {
let n_threads = 8;
let mut data = vec![0u8; 2_000_000]; // pretend this is 2 GiB
let mut data = &mut data[..];
let chunk_size = data.len() / n_threads;
thread::scope(|s| {
for _ in 0..n_threads {
let (chunk, rest) = data.split_at_mut(chunk_size);
data = rest;
s.spawn(move |_| {
chunk.fill(1);
});
}
})
.unwrap();
}
除了kmdreko推荐的优质人造丝板条箱之外,还有一种更低级的原型机,可以满足您的需求。您可以使用它将现有可变切片拆分为多个可变切片,而无需使用不安全代码:
let mut data = vec![0u8; 2_000_000]; // pretend this is 2 GiB
let mut data = &mut data[..];
let chunk_size = data.len() / n_threads;
for _ in 0..n_threads {
let (chunk, rest) = data.split_at_mut(chunk_size);
data = rest;
spawn(move |_| {
chunk.fill(1);
});
}
但是,要使其工作,您需要作用域线程,即允许引用借用值的线程。(这是合理的,因为作用域线程会自动连接所有创建的线程,从而确保没有线程比借用的值更长寿。)
下面是一个例子,使用与kmdreko的回答类似的设置:
use crossbeam_utils::thread;
fn main() {
let n_threads = 8;
let mut data = vec![0u8; 2_000_000]; // pretend this is 2 GiB
let mut data = &mut data[..];
let chunk_size = data.len() / n_threads;
thread::scope(|s| {
for _ in 0..n_threads {
let (chunk, rest) = data.split_at_mut(chunk_size);
data = rest;
s.spawn(move |_| {
chunk.fill(1);
});
}
})
.unwrap();
}
没有细节,很难给你一个精确的解决方案。但是你应该看看这个例子:这能回答你的问题吗?没有细节,很难给你一个精确的解决方案。但是你应该看看这个例子:这能回答你的问题吗?