从多个线程调用Eigen SimplicialLLT时,结果不正确
我正在尝试使用SimplicialLLT来计算SparseMatrix。由于我的程序在循环中运行,并且每个稀疏矩阵都不同,因此我尝试按如下方式并行化对SimplicialLLT的调用。这不是确切的运行代码。我已尝试复制进行调用的部分。
#include <iostream>
#include <cstdlib>
#include "Eigen/Core"
#include "Eigen/LU"
#include "Eigen/Sparse"
#include "Eigen/StdVector"
#include <thread>
#include <mutex>
#define NROW 4
void subProg1(int ii, int nodes);
using namespace std;
int main()
{
int imax = 4;
int ii, nodes;
std::thread threadpointer[4];
nodes = 20000;
for (ii=0;ii<imax;ii++) {
threadpointer[ii] = std::thread(subProg1,ii,nodes);
//threadpointer[ii].join();
}
for (ii=0;ii<imax;ii++) {
threadpointer[ii].join();
}
}
void subProg1(int IROW, int nodes)
{
static vector<SparseMatrix<double>> Kmat(NROW, SparseMatrix<double> (nodes*3,nodes*3));
static vector<SimplicialLLT<SparseMatrix<double>>> Kmat_LLT(Kmat.size());
//Asign Kmat values here
//Kmat[IROW] = ....
//Invert Kmat using SimplicialLLT
cout<< " Before Kmat_LLT IROW :" <<IROW<<endl;
Kmat_LLT[IROW].compute(Kmat[IROW]);
cout<< " After Kmat_LLT IROW:" <<IROW<<endl;
}
我在调用subProg1之后立即加入线程时得到的结果不同,因为线程在所有subProg1调用之后都在单独的循环中联接。我正在试图确定为什么会发生这种情况。Cout语句显示以下
当线程在调用后立即加入时(实质上是在没有多线程的情况下运行)
before Kmat_LLT IROW: 0
after Kmat_LLT IROW: 0
before Kmat_LLT IROW: 1
after Kmat_LLT IROW: 1
before Kmat_LLT IROW: 2
after Kmat_LLT IROW: 2
before Kmat_LLT IROW: 3
after Kmat_LLT IROW: 3
将subProg1作为多线程的一部分调用并在所有调用完成后加入
before Kmat_LLT IROW : 3
before Kmat_LLT IROW: 0
before Kmat_LLT IROW: 1
before Kmat_LLT IROW: 2
after Kmat_LLT IROW : 2
after Kmat_LLT IROW: 0
after Kmat_LLT IROW: 1
after Kmat_LLT IROW: 3
我不确定为什么kmat_lt[IROW]的结果在这两种方法之间是不同的。不知道subProg1中kmat_llt的声明是否有错误。如有任何帮助,我们不胜感激。
解决方案
您的问题实际上可能与计算无关。它与std::cout一起使用。C++流只在一次调用中是线程安全的。您的所有线程都试图同时写入cout,并开始彼此绊倒,可能会完成彼此的行。有两个简单的解决方案:
- 将屏幕上应该一起显示的所有内容(即整行)放在一个打印文件中。
- 首先将所有内容放入std::ostrgstream中,然后在一次操作中将ostrgstream写入cout。
在C++20中,您可以改用同步输出流。 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0053r0.html
相关文章