gpt4 book ai didi

multithreading - Rust-将函数引用传递给线程

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

说我有一个像这样的结构:

pub struct MyStruct {
f: Arc<dyn Fn(Vec<f64>) -> Vec<f64>>,
}

impl MyStruct {
pub fn new(f: Arc<dyn Fn(Vec<f64>) -> Vec<f64>>) -> MyStruct {
MyStruct { f }
}

pub fn start(&self) {
for _ in 0..5 {
let f = self.f.clone();
thread::spawn(move || {
let v: Vec<f64> = get_random_vector();
let v = (f)(v);
// do something with v
});
}
}
}

我收到一个错误消息,因为o​​jit_code类型没有实现 dyn Fn(Vec<f64>) -> Vec<f64>),所以该函数无法在线程之间安全地共享。

我可以做一个hack,可以将 Sync包装在Wrapper结构中,然后使用 Arc<dyn Fn(Vec<f64>) -> Vec<f64>将包装器标记为 Sync。但是我想知道是否有比这更好的解决方案。

现在,由于函数位于 unsafe impl内部,因此我们可以保证函数值是不可变的。

我还可以保证,对于 Arc的任何实例,向量的大小将始终是恒定的。可能是2、3或 MyStruct,但相同。因此,向量的大小是恒定的。因此,函数大小实际上是恒定的。

实际上,如果我使用 nVec<f64>代替 &[f64],则即使切片具有确定的大小,该函数仍不会实现 [f64]

那么,为什么不能在线程之间共享该函数,我该怎么做才能在线程之间共享呢?

最佳答案

为了将Arc发送到另一个线程,Arc需要实现Send。如果您查看the docs for Arc ,您会发现它具有

impl<T> Send for Arc<T> where
T: Send + Sync + ?Sized {}

这意味着要使您的代码正常工作,您的 T( dyn Fn(Vec<f64>) -> Vec<f64>)需要实现 SendSync

由于您的类型是特征对象,因此您需要声明,例如
pub struct MyStruct {
f: Arc<dyn Fn(Vec<f64>) -> Vec<f64> + Sync + Send>,
}

impl MyStruct {
pub fn new(f: Arc<dyn Fn(Vec<f64>) -> Vec<f64> + Sync + Send>) -> MyStruct {
MyStruct { f }
}
// ...
}

与之类似, T类型实现了所有这三个特征:
  • Fn(Vec<f64>) -> Vec<f64>
  • Sync
  • Send

  • 没有 Sync + Send特性,例如,您的 f函数可能会捕获对 Cell的引用,这会导致争用情况,因为多个线程可能会试图同时更新单元格的值。您的代码很可能不会这样做,但是您的 start函数无法知道这一点,除非您告诉它 f受到严格限制以至于不允许这样做。

    关于multithreading - Rust-将函数引用传递给线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59442080/

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