我在一些单线程代码中使用了Nalgebra的VectorN<f64, N>
类型,它运行良好。我现在正在尝试对算法的各个部分进行多线程处理,但在将VectorN
s传递到thread::spawn
调用中时遇到了问题。例如,以下代码编译失败:
use std::thread;
use nalgebra::{VectorN, DefaultAllocator, DimName};
use nalgebra::allocator::Allocator;
struct Test<N>
where
N: DimName,
DefaultAllocator: Allocator<f64, N>,
{
pub field: VectorN<f64, N>,
}
impl<N> Test<N>
where
N: DimName,
DefaultAllocator: Allocator<f64, N>,
{
pub fn test(&self) {
let handle = thread::spawn(move || {
let thing = self.field;
let thing2 = thing * 2.0;
thing2
});
let res = handle.join().unwrap();
}
}
出现此错误:
error[E0277]: `<nalgebra::base::default_allocator::DefaultAllocator as nalgebra::base::allocator::Allocator<f64, N>>::Buffer` cannot be sent between threads safely
--> trajectories/src/path/mod.rs:34:22
|
34 | let handle = thread::spawn(move || {
| ^^^^^^^^^^^^^ `<nalgebra::base::default_allocator::DefaultAllocator as nalgebra::base::allocator::Allocator<f64, N>>::Buffer` cannot be sent between threads safely
|
= help: within `nalgebra::base::matrix::Matrix<f64, N, nalgebra::base::dimension::U1, <nalgebra::base::default_allocator::DefaultAllocator as nalgebra::base::allocator::Allocator<f64, N>>::Buffer>`, the trait `std::marker::Send` is not
implemented for `<nalgebra::base::default_allocator::DefaultAllocator as nalgebra::base::allocator::Allocator<f64, N>>::Buffer`
= note: required because it appears within the type `nalgebra::base::matrix::Matrix<f64, N, nalgebra::base::dimension::U1, <nalgebra::base::default_allocator::DefaultAllocator as nalgebra::base::allocator::Allocator<f64, N>>::Buffer>`
= note: required by `std::thread::spawn`
我在where
子句中尝试了N
和DefaultAllocator
的各种定义,但还没有深入。各种各样的搜索引擎在这个问题上都没有找到任何有用的东西。
如果我用VectorN<f64, U3>
(或Nalgebra中的任何其他U*
类型(替换VectorN<f64, N>
,则上述错误将消失。我读过Nalgebra通用编程指南,但它似乎已经过时了,也许不是我需要的;我不想要完整的泛型,只想要使用任何大小绑定的VectorN
的能力。我需要在结构上设置什么特征边界,以便将field
传递到线程中?
我在黑暗中尝试了一下(基于编译器给出的错误消息(,并通过向Allocator::Buffer
添加边界来实现这一点,如下所示:
use nalgebra::allocator::Allocator;
struct Test<N>
where
N: DimName,
DefaultAllocator: Allocator<f64, N>,
<DefaultAllocator as Allocator<f64, N>>::Buffer: Send + Sync,
{
pub field: VectorN<f64, N>,
}
// snip ...
我不确定这是正确的方法,它确实会添加一些噪音,但现在它似乎让我可以将Nalgebra构造传递到线程中。