使用 OMP 进行多次 Eigen::Matrix 初始化:分段错误

Multiple Eigen::Matrix initializations with OMP: segmentation faults

在下面的最小示例中,我试图在由 OMP 并行化的 for 循环中创建一些 Eigen::Matrix。每个矩阵都包含在循环中,因此线程之间没有数据共享或竞争条件。当线程数等于一个时,代码可以完美运行,否则我会遇到分段错误。令人难以置信的是,我遇到大小为 600x600 的矩阵的段错误,但对于 599x599 或 601x601 或 1000x1000 的矩阵却没有。任何帮助表示赞赏。谢谢:)

#include <iostream>

#define EIGEN_DONT_ALIGN_STATICALLY
#define EIGEN_STACK_ALLOCATION_LIMIT 0
#include <Eigen/Core>

#define SIZE 600
#define THREADS 2

int main(int argc, char *argv[]) {

  // The following code always works for THREADS=1
  // When THREADS!=1, there is a seg fault if SIZE=600. 
  // There is no seg fault when THREADS!=1 and SIZE=599 or SIZE=601
  
  #pragma omp parallel for num_threads(THREADS)
  for(int n=0; n<5; ++n){
    Eigen::Matrix<double,SIZE,SIZE> mat =  Eigen::Matrix<double,SIZE,SIZE>::Zero();
  }

  return 0;
}


问题来自 固定大小 和有限的 堆栈大小 。事实上,Matrix<double,SIZE,SIZE> 分配在堆栈上,并且由于 SIZE 相当大,它应该在大多数系统上分配 2.7 MiB,而堆栈大小通常设置为几 MiB(默认情况下设置为 2 MiB 在大多数 Linux 平台)。您应该改用 Dynamic 矩阵大小

有关详细信息,请参阅 the documentation

The limitation of using fixed sizes, of course, is that this is only possible when you know the sizes at compile time. Also, for large enough sizes, say for sizes greater than (roughly) 32, the performance benefit of using fixed sizes becomes negligible. Worse, trying to create a very large matrix using fixed sizes inside a function could result in a stack overflow, since Eigen will try to allocate the array automatically as a local variable, and this is normally done on the stack.

默认情况下,派生线程的堆栈大小可能比主线程小得多。因此,上面的代码在生成的线程上遇到堆栈溢出。 Jérôme Richard 的替代解决方案是通过环境变量 OMP_STACKSIZE.

增加生成线程的堆栈大小