如何解决为什么当 std::thread 用于多线程时,特征矩阵计算返回零?
我正在尝试实现多线程以将某些 CPU 密集型操作分配给不同的线程。然而,当使用多线程时,任何 Eigen 声明总是返回零。以下是演示此问题的示例代码
#include "../Eigen/Core"
#include "../Eigen/LU"
#include "../Eigen/Sparse"
#include "../Eigen/StdVector"
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
using namespace Eigen;
void Multiply_3x3 (MatrixXd& matrix1,MatrixXd& matrix2,MatrixXd& results);
int main()
{
MatrixXd a(3,3);
MatrixXd b(3,3);
MatrixXd c(3,3);
a<<2,4,3,1,5,7,2,3;
b<<2,3;
//Multiply_3x3(a,b,c);
std::thread thread_multi(Multiply_3x3,a,c);
thread_multi.join();
cout << " *** In Main Program ***" << endl;
cout <<c(0,0)<<","<< c(0,1)<<",1)<<endl;
cout<<c(1,"<<c(1,1)<<endl;
cout<<c(2,"<<c(2,1)<<endl;
}
void Multiply_3x3 (MatrixXd& matrix1,MatrixXd& results)
{
results = matrix1 * matrix2;
cout << " *** In Multiply_3x3 ***" << endl;
cout<<results(0,"<<results(0,1)<<endl;
cout<<results(1,"<<results(1,1)<<endl;
cout<<results(2,"<<results(2,1)<<endl<<endl<<endl;
}
这次运行的输出是
*** In Multiply_3x3 ***
8,34,34
7,43,43
2,16,16
*** In Main Program ***
1.69122e-306,1.95819e-306,1.95819e-306
9.34612e-307,6.23037e-307,6.23037e-307
9.34602e-307,6.2304e-307,6.2304e-307
如输出所示,函数 Multiply_3x3 中的结果是正确的。但是返回的值为零。如果我不使用 std:thread 并按照推荐部分 (//Multiply_3x3(a,c);) 中所示调用函数,则调用函数中的结果是正确的。想知道是否有人可以指出我在这里遗漏了什么。
解决方法
在构造 std::ref
时,您必须将 a
应用于所有矩阵 b
、c
和 thread
。如果没有这个,std::thread
会复制传递的参数并对它们进行操作,更改 c
矩阵的副本而不是 c
中定义的原始 main
矩阵。
std::thread thread_multi(Multiply_3x3,std::ref(a),std::ref(b),std::ref(c));
thread_multi.join();
请注意,如果没有 std::ref
,您的代码无法在 G++ 上编译,您似乎正在使用具有一些扩展(默认启用)的 Microsoft Visual - 例如,将临时对象绑定到 lvalue 参考。这就是编译您的代码的原因。您可以通过将 /Za
添加到编译器的标志来关闭此功能。
不完全确定你是如何编译和工作的。我无法在 MSVC 上编译它。
但是,请记住,std::thread
的构造函数并不关心传入参数的类型。它只是将参数复制到内部存储(可由新创建的线程访问)并传入作为可调用对象的临时对象(右值)。
例如
void foo(std::string& s);
std::thread t1(foo,"hello");
std::string arg("hello");
std::thread t2(foo,arg);
将无法工作,因为不可能从临时对象构造非常量引用。
但是
void foo(const std::string& s);
std::thread t1(foo,arg);
没问题,因为该函数接受一个 const
引用。
所以你只需要用 std::ref
包装需要引用的参数,这样函数就不会得到临时副本。然后它将编译并正常工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。