Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 人造丝中的每线程初始化_Multithreading_Rust_Rayon - Fatal编程技术网

Multithreading 人造丝中的每线程初始化

Multithreading 人造丝中的每线程初始化,multithreading,rust,rayon,Multithreading,Rust,Rayon,我正在尝试使用人造丝的par_iter()优化我的功能 单线程版本类似于: fn verify_and_store(store: &mut Store, txs: Vec<Tx>) { let result = txs.iter().map(|tx| { tx.verify_and_store(store) }).collect(); ... } 但是,这会在每次迭代时克隆存储,这太慢了。我希望每个线程使用一个存储实例 人造

我正在尝试使用人造丝的
par_iter()
优化我的功能

单线程版本类似于:

fn verify_and_store(store: &mut Store, txs: Vec<Tx>) {

    let result = txs.iter().map(|tx| {

         tx.verify_and_store(store)

    }).collect();

    ...
}
但是,这会在每次迭代时克隆
存储
,这太慢了。我希望每个线程使用一个存储实例


人造丝可以吗?或者我应该求助于手动线程和工作队列吗?

可以使用线程局部变量来确保在给定线程中创建的
local\u store
不会超过一次

例如,它编译():


老问题,但我觉得答案需要重新审视。一般来说,有两种方法:

与一起使用
map\u。每当一个线程从另一个线程窃取一个工作项时,就会进行克隆。这可能会克隆比线程多的存储,但应该相当低。如果克隆成本太高,您可以使用
增加rayon将拆分工作负载的大小

fn verify_and_store(store: &mut Store, txs: Vec<Tx>) {
    let result = txs.iter().map_with(|| store.clone(), |store, tx| {
         tx.verify_and_store(store)
    }).collect();
    ...
}

很遗憾,这个调用似乎没有任何作用域(尽管这在相当多的情况下显然是有用的)。@ChrisEmerson是的,这个答案让我担心的是,我想不出一种方法来使用安全代码清理创建的存储(或者在一切完成后运行其他任意命令,例如将它们刷新到磁盘)。更糟糕的是,下一次调用
verify_and_store
将继续使用最后一个已知的
store
克隆,这些克隆可能与当前的
store
无关。谢谢。这是可行的,但在我的特殊情况下,我发现人造丝有
par_块
来减少克隆的数量。虽然这可能仍然会导致每个线程有多个克隆,但它不存在@user4815162342描述的范围问题。@ChrisEmerson我现在已经更新了答案,以添加范围和适当的清理;代码并不优雅(至少可以这么说),但它似乎可以工作@Tomas您可能想添加您的解决方案作为答案,并接受它。我的答案是有趣地探索Rust/Rayon对线程本地代码的支持,而您的
par_chunks
解决方案似乎在解决实际问题方面做得很好。
fn verify_and_store(store: &mut Store, txs: Vec<Tx>) {
    use std::cell::RefCell;
    thread_local!(static STORE: RefCell<Option<Store>> = RefCell::new(None));

    let mut result = Vec::new();

    txs.par_iter().map(|tx| {
        STORE.with(|cell| {
            let mut local_store = cell.borrow_mut();
            if local_store.is_none() {
                *local_store = Some(store.clone());
            }
            tx.verify_and_store(local_store.as_mut().unwrap())
        })
    }).collect_into(&mut result);
}
fn verify_and_store(store: &mut Store, txs: Vec<Tx>) {
    use std::sync::{Arc, Mutex};
    type SharedStore = Arc<Mutex<Option<Store>>>;

    lazy_static! {
        static ref STORE_CLONES: Mutex<Vec<SharedStore>> = Mutex::new(Vec::new());
        static ref NO_REENTRY: Mutex<()> = Mutex::new(());
    }
    thread_local!(static STORE: SharedStore = Arc::new(Mutex::new(None)));

    let mut result = Vec::new();
    let _no_reentry = NO_REENTRY.lock();

    txs.par_iter().map({
        |tx| {
            STORE.with(|arc_mtx| {
                let mut local_store = arc_mtx.lock().unwrap();
                if local_store.is_none() {
                    *local_store = Some(store.clone());
                    STORE_CLONES.lock().unwrap().push(arc_mtx.clone());
                }
                tx.verify_and_store(local_store.as_mut().unwrap())
            })
        }
    }).collect_into(&mut result);

    let mut store_clones = STORE_CLONES.lock().unwrap();
    for store in store_clones.drain(..) {
        store.lock().unwrap().take();
    }
}
fn verify_and_store(store: &mut Store, txs: Vec<Tx>) {
    let result = txs.iter().map_with(|| store.clone(), |store, tx| {
         tx.verify_and_store(store)
    }).collect();
    ...
}
fn verify_and_store(store: &mut Store, txs: Vec<Tx>) {
    let tl = ThreadLocal::new();
    let result = txs.iter().map(|tx| {
         let store = tl.get_or(|| Box::new(RefCell::new(store.clone)));
         tx.verify_and_store(store.get_mut());
    }).collect();
    ...
}