首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用rayon并行迭代器时同步和发送特征

使用rayon并行迭代器时同步和发送特征
EN

Stack Overflow用户
提问于 2020-06-15 00:00:06
回答 1查看 465关注 0票数 3

我有一个我的特征的集合,我希望能够为我的map中的每个项目调用特征的可变方法。

目前,我按顺序执行此操作,我的集合如下所示:

代码语言:javascript
复制
use std::cell::RefCell;
use std::collections::*;
use std::rc::Rc;

trait Trait {
    fn foo_mut(&mut self);
}

fn main() {
    let mut items: HashMap<i32, Rc<RefCell<dyn Trait>>> = HashMap::new();
    // I have a separate data structure that holds Week<RefCell<dyn Trait>>

    for item in items.values_mut() {
        item.borrow_mut().foo_mut();
    }
}

现在我想并行调用特征方法,所以我首先将我的数据结构改为:

代码语言:javascript
复制
use std::collections::*;
use std::sync::{Arc, RwLock};

fn main() {
    let mut items: HashMap<i32, Arc<RwLock<dyn Trait>>> = HashMap::new();

    for item in items.values_mut() {
        item.write().unwrap().foo_mut();
    }
}

然后我遇到了rayon,我尝试使用它的并行迭代器,但是下面的代码引发了一个错误:

代码语言:javascript
复制
items.par_iter_mut().for_each(|(id, item)| item.write().unwrap().foo_mut());
代码语言:javascript
复制
error[E0599]: no method named `par_iter_mut` found for struct `std::collections::HashMap<i32, std::sync::Arc<std::sync::RwLock<dyn Trait>>>` in the current scope
   --> src/main.rs:12:11
    |
12  |       items.par_iter_mut().for_each(|(id, item)| item.write().unwrap().foo_mut());
    |             ^^^^^^^^^^^^ help: there is an associated function with a similar name: `iter_mut`
    |
    = note: the method `par_iter_mut` exists but the following trait bounds were not satisfied:
            `&mut std::collections::HashMap<i32, std::sync::Arc<std::sync::RwLock<dyn Trait>>>: rayon::iter::IntoParallelIterator`
            which is required by `std::collections::HashMap<i32, std::sync::Arc<std::sync::RwLock<dyn Trait>>>: rayon::iter::IntoParallelRefMutIterator`

我查看了for_each文档,它要求Self::ItemSend,闭包为Send + Sync,现在我可以看到Arc已经是Send + Sync了,但是可以通过将这两个特征添加到我的代码中来修复代码,如下所示:

代码语言:javascript
复制
let mut items: HashMap<i32, Arc<RwLock<dyn Trait + Send + Sync>>> = HashMap::new();

为什么这是必要的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-15 05:19:04

用于Arc<T>SendSync的实现类似于this

代码语言:javascript
复制
impl<T> Send for Arc<T>
where
    T: Send + Sync + ?Sized, 

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

这意味着Arc<T>仅为Send,如果T也为Sync,则为Sync(请参阅here以了解原因)。

同样,如果Tis,则RwLock<T>仅为SendSync

代码语言:javascript
复制
impl<T: ?Sized + Send> Send for RwLock<T>
impl<T: ?Sized + Send + Sync> Sync for RwLock<T>

总而言之,这意味着如果dyn Trait也是,那么Arc<RwLock<dyn Trait>>将只是SendSync。如果编写dyn Trait + Send + Sync很麻烦,并且您知道您永远不想为任何类型不是SendSync的类型实现Trait,那么您可以将这些作为边界添加到特征中:

代码语言:javascript
复制
trait Trait: Send + Sync {
    fn foo_mut(&mut self);
}

然后,您使用Arc<RwLock<dyn Trait>>编写的原始代码将与rayon一起工作。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62374960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档