繁体   English   中英

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

[英]Multiple Eigen::Matrix initializations with OMP: segmentation faults

在以下最小示例中,我尝试在由 OMP 并行化的 for 循环中创建一些 Eigen::Matrix。 每个矩阵都包含在循环中,因此线程之间没有数据共享或竞争条件。 当线程数等于 1 时,代码可以完美运行,否则会出现分段错误。 令人难以置信的是,我得到了大小为 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(在大多数 Linux 平台上默认设置为 2 MiB )。 您应该改用Dynamic矩阵大小

有关更多信息,请参阅文档

当然,使用固定大小的限制是只有在编译时知道大小时才有可能。 此外,对于足够大的尺寸,例如大于(大约)32 的尺寸,使用固定尺寸的性能优势变得可以忽略不计。 更糟糕的是,尝试在 function 中使用固定大小创建一个非常大的矩阵可能会导致堆栈溢出,因为 Eigen 会尝试将数组自动分配为局部变量,而这通常在堆栈上完成。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM