我有一个像这样的数组(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中使用“优化”?
答案 0 :(得分:2)
首先,用户High Performance Mark在他的评论中是正确的。如果循环索引值取决于计算的值,则不应该使用折叠。在你的例子中,&#34; j&#34;取决于&#34; max&#34;,这将产生不正确的结果。但是,这不是导致分段错误的原因。
我建议您调试您的示例,以便找到崩溃的来源; &#34; MAX&#34;默认情况下正在使用负数进行初始化,这会导致&#34; j&#34;也有说的价值。因此,当尝试访问数组[i * height +( - 2147483648)]时,会出现分段错误。
这是因为OpenMP为每个简化运算符指定了初始值。对于 max运算符,您可以在specification of OpenMP 3.1中找到以下说明:
max 缩减列表项目类型
中的最不可表示的值
在我们的例子中,这意味着每个线程将在并行区域的开头有一个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并使用之前的位置。
希望有所帮助