我已经编写了一些代码来将计算的独立块分解成块,然后将每个块提供给线程池,然后执行计算并将结果通过mpsc
传递回主线程。
代码如下:
pub fn impute(pbwt_data : Arc<&pbwt::PbwtInfo>, test_sequences : Vec<Vec<u8>>) -> Vec<Vec<u8>> {
let N = test_sequences.len();
let mut fin_imputed: Vec<Vec<u8>> = vec![Vec::new();N];
let safe_pbwt = Arc::new(pbwt_data);
let (tx,rx) = mpsc::channel();
let pool = ThreadPool::new(8);
let mut i = 0;
for tst_seq in test_sequences.into_iter(){
let txr = tx.clone();
let safe_test_seq = Arc::new(tst_seq);
let refer = Arc::clone(&safe_pbwt);
let clo = closure!(move txr, move refer, move safe_test_seq, || {
let val = impute_single(&refer,&safe_test_seq);
let ret = RowWPos { position: i as u32, row: val};
txr.send(ret).unwrap();
});
pool.execute(clo);
i += 1;
}
drop(tx);
for recd in rx.iter() {
fin_imputed[recd.position as usize] = recd.row;
}
return fin_imputed;
}
内部impute_single
函数引用一个PbwtInfo
对象和一个Vec<u8>
对象。内部函数不以任何方式修改PbwtInfo
对象,它只是从中读取。
不幸的是,当我试图运行它时,这段代码产生了一个错误:
error[E0521]: borrowed data escapes outside of function
--> pbwt_hkhan/src/imputer.rs:138:9
|
111 | pub fn impute(pbwt_data : Arc<&pbwt::PbwtInfo>, test_sequences : Vec<Vec<u8>>) -> Vec<Vec<u8>> {
| --------- - let's call the lifetime of this reference `'1`
| |
| `pbwt_data` is a reference that is only valid in the function body
...
138 | pool.execute(clo);
| ^^^^^^^^^^^^^^^^^
| |
| `pbwt_data` escapes the function body here
| argument requires that `'1` must outlive `'static`
For more information about this error, try `rustc --explain E0521`.
error: could not compile `pbwt_hkhan` due to previous error
我可以通过将函数签名中的pbwt_data : Arc<&pbwt::PbwtInfo>
更改为pbwt_data : Arc<pbwt::PbwtInfo>
并直接使用PbwtInfo
对象创建Arc
而不是在将其提供给函数之前引用它来修复此错误。然而,这意味着我的对象现在卡在Arc内部,并且在下游有进一步的代码,我想再次使用PbwtInfo
对象。
我可以克隆它,但它是一个相当大的和昂贵的对象创建一个副本,所以我宁愿不这样做。理想情况下,我想要一个解决方案,我甚至不必将Arc传递给impute
函数,并且可以只使用&PbwtInfo
,因为它或它调用的任何东西都不会修改pbwt_data
。我知道我可以做到这一点,如果不是将计算分割成块并使用线程池,我只是使用单个线程,所以我觉得这应该是可能的。
使用Arc<pbwt::PbwtInfo>
作为类型。要再次检索对象,可以使用Arc::try_unwrap(your_arc)
,如果只剩下一个强引用,它将给出该对象。