我有一个巨大的向量,我希望能够并行加载/操作,例如,在一个线程中加载前十万个索引,在另一个线程中加载下一个,依此类推.由于这将成为代码中非常热门的一部分,我已经提出了以下概念验证不安全代码,以便在没有Arcs和Mutexes的情况下执行此操作:
let mut data:Vec<u32> = vec![1u32, 2, 3];
let head = data.as_mut_ptr();
let mut guards = (0..3).map(|i|
unsafe {
let mut target = std::ptr::Unique::new(head.offset(i));
let guard = spawn(move || {
std::ptr::write(target.get_mut(), 10 + i as u32);
});
guard
});
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么可以使这可能爆炸吗?
这使用#![feature(unique)]
所以我不知道如何在稳定中使用它.有没有办法在稳定中做这种事情(理想情况下安全,不使用原始指针和开销的Arc
's和Mutex
's)?
另外,看一下 文档Unique
,它说
它还意味着如果没有引用的唯一路径,则不应修改指针的
Unique
引用
我不清楚"独特路径"是什么意思.
我是Rust的新手,并努力处理Rust中的所有包装器类型.我试图编写在语义上等于以下C代码的代码.代码尝试创建一个用于簿记的大表,但是会分割大表,以便每个线程只访问该表的本地小片.除非其他线程退出并且不再访问自己的切片,否则不会访问大表.
#include <stdio.h>
#include <pthread.h>
void* write_slice(void* arg) {
int* slice = (int*) arg;
int i;
for (i = 0; i < 10; i++)
slice[i] = i;
return NULL;
}
int main()
{
int* table = (int*) malloc(100 * sizeof(int));
int* slice[10];
int i;
for (i = 0; i < 10; i++) {
slice[i] = table + i * 10;
}
// create pthread for each slice
pthread_t p[10];
for (i = 0; i < 10; i++)
pthread_create(&p[i], NULL, write_slice, …
Run Code Online (Sandbox Code Playgroud) 我遇到多个线程必须更新存储在共享向量中的对象的情况。但是,向量非常大,并且要更新的元素数量相对较少。
在最小示例中,可以通过包含要更新的元素的索引的(哈希)集来标识要更新的元素集。因此,代码如下所示:
let mut big_vector_of_elements = generate_data_vector();
while has_things_to_do() {
let indices_to_update = compute_indices();
indices_to_update.par_iter() // Rayon parallel iteration
.map(|index| big_vector_of_elements[index].mutate())
.collect()?;
}
Run Code Online (Sandbox Code Playgroud)
Rust显然不允许这样做:big_vector_of_elements
不能同时在多个线程中可变地借用。但是,将每个元素包装在例如Mutex
锁中似乎是不必要的:如果没有明确的同步,这种特定情况将是安全的。由于索引来自一组,因此可以保证它们是不同的。par_iter
在向量的相同元素上没有两次迭代。
编写一个并行修改向量中元素的程序的最佳方法是什么,在这种情况下,同步已经通过选择索引来解决,但是编译器不理解后者呢?
接近最佳的解决方案是将所有元素包装big_vector_of_elements
在某种假设的UncontendedMutex
锁中,这是其变体,Mutex
在无竞争的情况下非常快,并且在发生争用(甚至发生恐慌)时可能会花费任意长时间。理想情况下,an UncontendedMutex<T>
的大小和对齐方式也应与T
any相同T
。
可以使用“使用人造丝的并行迭代器”,“使用chunks_mut
”或“使用split_at_mut
” 来回答多个问题:
这些答案在这里似乎无关紧要,因为这些解决方案意味着迭代整个big_vector_of_elements
,然后针对每个元素弄清楚是否需要更改任何内容。从本质上讲,这意味着这样的解决方案如下所示:
let mut big_vector_of_elements = generate_data_vector();
while has_things_to_do() {
let indices_to_update = compute_indices();
for (index, mut element) in big_vector_of_elements.par_iter().enumerate() …
Run Code Online (Sandbox Code Playgroud) 我正在尝试跨线程分发数组并让线程并行地对数组的部分进行求和.我希望线程0对元素0 1 2和线程1求和元素3 4 5进行求和.将线程2加到6和7,将线程3加到8和9之和.
我是Rust的新手,但之前用C/C++/Java编写过代码.我真的把所有东西都扔到了这个程序的垃圾槽里,我希望能得到一些指导.
对不起我的代码很邋but但是当它是成品时我会把它清理干净.请忽略所有命名不佳的变量/不一致的间距/等.
use std::io;
use std::rand;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread::Thread;
static NTHREADS: usize = 4;
static NPROCS: usize = 10;
fn main() {
let mut a = [0; 10]; // a: [i32; 10]
let mut endpoint = a.len() / NTHREADS;
let mut remElements = a.len() % NTHREADS;
for x in 0..a.len() {
let secret_number = (rand::random::<i32>() % 100) + 1;
a[x] = secret_number;
println!("{}", a[x]);
}
let mut b = a;
let …
Run Code Online (Sandbox Code Playgroud) 我有两个从另一个方法传递过来的切片:
fn example<T>(a1: &[T], a2: &mut [T]) {}
Run Code Online (Sandbox Code Playgroud)
我想a1
使用多个线程进行处理,然后a2
使用仅在每个线程执行时才知道的完全任意索引写入。我的算法保证索引是互斥的,所以没有数据竞争。
借用检查器不喜欢在线程之间共享可变引用,因为它不知道我们的算法所做的保证。我也收到lifetime 'static required rustc (E0621)
错误。
那么如何在 Rust 中做到这一点呢?
回答
不要回答我的问题。
第一个问题的答案解决了范围问题,而不是访问任意互不相交的索引的问题。第二个问题的答案表明,as_slice_of_cells
但由于上述原因,即任意访问,这在这里不起作用。第三个问题的答案同样暗示,as_slice_of_cells
但同样,数组可以分成不相交的部分的假设在这里无法实现。第四个问题再次询问对数组进行分区,我们在这里不能这样做。这同样适用于第五个问题。
范围界定问题的一个答案(/sf/answers/4515197711/)实际上试图解决这个问题,但它并不建议使用横梁,并且建议的替代方案比此处的最佳答案更不安全。