相关疑难解决方法(0)

如何同时获得对两个数组元素的可变引用?

fn change(a: &mut i32, b: &mut i32) {
    let c = *a;
    *a = *b;
    *b = c;
}

fn main() {
    let mut v = vec![1, 2, 3];
    change(&mut v[0], &mut v[1]);
}
Run Code Online (Sandbox Code Playgroud)

当我编译上面的代码时,它有错误:

error[E0499]: cannot borrow `v` as mutable more than once at a time
 --> src/main.rs:9:32
  |
9 |         change(&mut v[0], &mut v[1]);
  |                     -          ^   - first borrow ends here
  |                     |          |
  |                     |          second mutable borrow occurs here
  |                     first mutable borrow occurs here …
Run Code Online (Sandbox Code Playgroud)

rust

28
推荐指数
5
解决办法
5898
查看次数

如何将对堆栈变量的引用传递给线程?

我正在编写一个WebSocket服务器,其中一个Web客户端连接到多线程计算机AI上下棋.WebSocket服务器想要将Logger对象传递给AI代码.该Logger对象将管理从AI到Web客户端的日志行.在Logger必须包含对客户端连接的参考.

我对生命周期如何与线程交互感到困惑.我用Wrapper类型参数化的结构重现了这个问题.该run_thread函数尝试解包该值并记录它.

use std::fmt::Debug;
use std::thread;

struct Wrapper<T: Debug> {
    val: T,
}

fn run_thread<T: Debug>(wrapper: Wrapper<T>) {
    let thr = thread::spawn(move || {
        println!("{:?}", wrapper.val);
    });

    thr.join();
}

fn main() {
    run_thread(Wrapper::<i32> { val: -1 });
}
Run Code Online (Sandbox Code Playgroud)

wrapper参数存在于堆栈中,并且它的生命周期不会延伸超过run_thread堆栈帧,即使该线程将在堆栈帧结束之前连接.我可以从堆栈中复制值:

use std::fmt::Debug;
use std::thread;

struct Wrapper<T: Debug + Send> {
    val: T,
}

fn run_thread<T: Debug + Send + 'static>(wrapper: Wrapper<T>) {
    let thr = thread::spawn(move || …
Run Code Online (Sandbox Code Playgroud)

rust

22
推荐指数
1
解决办法
3771
查看次数

并行处理vec:如何安全地进行,或者不使用不稳定的功能?

我有一个巨大的向量,我希望能够并行加载/操作,例如,在一个线程中加载前十万个索引,在另一个线程中加载下一个,依此类推.由于这将成为代码中非常热门的一部分,我已经提出了以下概念验证不安全代码,以便在没有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引用

我不清楚"独特路径"是什么意思.

parallel-processing unsafe rust

9
推荐指数
2
解决办法
1548
查看次数

如何将不相交的切片从向量传递到不同的线程?

我是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)

rust

6
推荐指数
1
解决办法
1527
查看次数

同时可变地访问保证向量不相交的大向量的任意索引

语境

我遇到多个线程必须更新存储在共享向量中的对象的情况。但是,向量非常大,并且要更新的元素数量相对较少。

问题

在最小示例中,可以通过包含要更新的元素的索引的(哈希)集来标识要更新的元素集。因此,代码如下所示:

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>的大小和对齐方式也应与Tany相同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)

vector rust thread-synchronization rayon

5
推荐指数
2
解决办法
222
查看次数

如何在分区数组上运行并行计算线程?

我正在尝试跨线程分发数组并让线程并行地对数组的部分进行求和.我希望线程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)

random multithreading synchronization rust

4
推荐指数
2
解决办法
3234
查看次数

不同的线程可以写入同一Vec的不同部分吗?

我有10个线程Vec,长度为100.

我可以在0-9元素(例如,排序它们)上使用线程0,而线程1正在处理元素10-19等等吗?

或者我必须使用Vec<Vec<>>这个吗?(我宁愿避免,因为元素在内存中不再是连续的)

rust

3
推荐指数
1
解决办法
460
查看次数