从多个线程调用Eigen SimplicialLLT时,结果不正确 [英] Eigen SimplicialLLT gives incorrect results when called from multiple threads

查看:75
本文介绍了从多个线程调用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,并开始彼此绊倒,可能会完成彼此的行。有两个简单的解决方案:

  1. 将屏幕上应该一起显示的所有内容(即整行)放在一个打印文件中。
  2. 首先将所有内容放入std::ostrgstream中,然后在一次操作中将ostrgstream写入cout。

在C++20中,您可以改用同步输出流。 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0053r0.html

这篇关于从多个线程调用Eigen SimplicialLLT时,结果不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆