传递私有变量时的Openmp段错误,但在并行区域内声明变量时则不会

时间:2017-01-10 15:58:27

标签: c parallel-processing openmp

标题说明了一切。当我在并行区域外声明数组x并将其作为私有变量传递给线程时,我得到一个段错误。 当我在并行区域内声明变量时,一切正常。 我有兴趣将变量作为私有而不是声明它,因此我需要帮助来调试问题。 这是它的样子:

//Case1 - doesn't work (segfault)
x = (double *) malloc (solution * sizeof(double));
#pragma omp parallel for private(x)
for...

//Case2 - works
#pragma omp parallel for 
for...
    x = (double *) malloc (solution * sizeof(double));

我正在使用72个线程,并且我已将KMP_STACKSIZE设置为1m以及

ulimit -s unlimited 

更新

尽管有约翰的建议,我仍然得到了段错误。这是实际的代码片段。我实际上正在使用CPLEX优化库。我也尝试使用memcpy进行私有变量分配。

#pragma omp parallel for private(i) shared(lp,env)
for(i=0;i<n;i++){
    CPXENVptr envi =env;
    CPXLPptr    lpi = lp
    CPXLpopt(envi,lpi);//this is where the segfault happens
}

值得注意的是CPLXLpopt命令会更改envi和lpi变量的大小/ 你推荐使用openmp的调试器吗?

1 个答案:

答案 0 :(得分:2)

关于一个代码工作而另一个代码的断言最多不是近似值。实际上, 代码甚至都没有成功编译。几乎可以肯定的是,在一个案例中报告的不当行为还取决于并行部分中变量x的使用方式。

话虽如此,如果工作代码和非工作代码之间的唯一区别是放置x的声明和赋值,如图所示,那么分配{{1的版本也就不足为奇了在并行区域segfaults之外。 OpenMP规范描述了在Case 1的并行区域中运行的每个线程中的私有x

  

为构造分配具有自动存储持续时间的相同类型的新列表项。 [...] 新列表项已初始化,或者具有未定义的初始值,就好像它是在没有初始化程序的情况下本地声明的那样。

(来自OpenMP 4.5,2.15.3.3;强调添加)

也就是说,并行循环中的本地x不是以循环外的(单独)x所具有的值开头的。它们的初始值是不确定的(对于没有初始化程序声明的自动对象,每个C)。使用该初始值会产生未定义的行为,这可能很好地表现为分段错误。

您可以通过允许共享x并在并行部分中使用不同的私有变量(从共享x初始化)来解决此问题。像这样的东西,例如:

x

x = (double *) malloc (solution * sizeof(double)); #pragma omp parallel for for (double *y = x; ... 是共享的,默认情况下x是私有的)。这适用于您希望每个线程都有一个私有指针到同一共享空间的场景。

但是,请注意,y指向的内存无论如何都会被共享。如果您希望每个线程都有自己独立的动态分配空间,那么每个线程都需要自己分配这样的空间(并随后释放该空间)。即使在这种情况下,分配的空间在技术上是共享的,但如果线程没有发布任何指向其分配空间的指针,那么其他线程将无法访问它们。