标题说明了一切。当我在并行区域外声明数组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的调试器吗?
答案 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
指向的内存无论如何都会被共享。如果您希望每个线程都有自己独立的动态分配空间,那么每个线程都需要自己分配这样的空间(并随后释放该空间)。即使在这种情况下,分配的空间在技术上是共享的,但如果线程没有发布任何指向其分配空间的指针,那么其他线程将无法访问它们。