我有一个这样的数组(0,0表示左下角):
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 1 0 1 0 1 0 0
0 0 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
我的目标是获得未完全设置为0
的较高行的索引。为此,我编写了以下代码(可以很好地工作):
max=0;
for (i=0 ; i<width ; ++i) {
for (j=max ; j<height ; ++j) {
if (array[i*height+j]!=0) {
max=j;
}
}
}
对于第二个循环,我将j
初始化为max,因为全局最大值不能小于局部最大值。这样我就可以减少测试的次数。
我试着把它和OpenMp
并行化。我的代码现在是:
max=0;
#pragma omp parallel for default(none) \
shared(spec, width, height) \
collapse(2) \
reduction(max:max)
for (i=0 ; i<width ; ++i) {
for (j=max ; j<height ; ++j) {
if (array[i*height+j]!=0) {
max=j;
}
}
}
这会导致分段故障。为了使其正常工作,我将j=max
更改为j=0
。所以问题似乎来自max
变量。
我不明白为什么,因为通过缩减,这个变量在每个线程之间应该是私有的(或lastprivate)。那么为什么它会让它崩溃呢?我如何在OpenMP中使用我的“优化”功能?
发布于 2018-06-19 01:17:20
首先,用户High Performance Mark的评论是对的。如果循环索引值依赖于计算的值,则不应该使用折叠。在您的示例中,"j“依赖于"max",这将产生错误的结果。然而,这并不是分段错误的原因。
我建议你调试你的例子,这样你就可以找到崩溃的来源;默认情况下,"max“是用负数初始化的,这会导致"j”也有这个值。因此,当尝试访问arrayi*height+(-2147483648)时,您会得到一个分段错误。
这是因为OpenMP为每个约简运算符指定了一个初始值。对于最大运算符,您可以在specification of OpenMP 3.1中找到以下描述
约简列表项类型中的
最大最小可表示值
在我们的例子中,这意味着每个线程在并行区域的起始处都有一个max变量的私有副本,该副本保存了可以存储为int (通常为-2147483648)的最低数值。
我已经为你的例子写了一个非常简单的变通方法。我删除了折叠子句,并在并行区域的开头手动初始化max变量:
#pragma omp parallel default(none) private(j) shared(array, width, height) reduction(max:max)
{
// Explicit initialization
max = 0;
#pragma omp for
for (i=0 ; i<width ; ++i) {
for (j=max ; j<height ; ++j) {
if (array[i*height+j]!=0) {
max=j;
}
}
}
}
作为额外的说明,您不应该每次都使用max=j。您可以尝试检查何时找到第一个0,并使用前一个位置。
希望能有所帮助
https://stackoverflow.com/questions/50911787
复制相似问题