我遇到了尝试重新编码嵌套for循环以便并行化的问题:
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
if(asubsref(struct1,j) > 0)
asubsref(struct2,j) = asubsref(struct3,j) + 1;
}
for(j=0; j<n; j++)
asubsref(struct1,j) = asubsref(struct2,j) - asubsref(struct3,i);
}
Struct1 / struct2是两个分别带有width / height / int-float数组的结构。 struct3是一个float结构。
我到目前为止的尝试是将它们分成两个不同的循环但是唉,它没有用,因为我得到了很多不正确的结果:
#pragma omp parallel
{
#pragma omp for private(j)
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
if(asubsref(struct1,j) > 0)
asubsref(struct2,j) += 1;
}
}
#pragma omp for private(j)
for(i=0; i<n; i++)
{
k = asubsref(struct3,i);
for (j=0; j<n; j++)
{
asubsref(struct1,j) -= k;
}
}
}
我不是在寻找答案,而是一些指导,帮助我思考如何解决这个问题/提示答案等。
答案 0 :(得分:4)
我在这段代码中看到的是三个数组:
array1: asubsref(seed,0) ... asubsref(seed,n-1)
array2: asubsref(bin,0) ... asubsref(bin,n-1)
array3: asubsref(w,0) ... asubsref(w,n-1)
如果这个假设是正确的并且asubsref不产生任何副作用,则可以导出以下不变量:
循环执行结束后,array2 [j]递增 数字x是最大数字,使得array3 [i]之和 对于从0到x的i小于array1 [j]。
这是你能做的。首先,你可以合并两个最里面的循环,因为(在我们的假设下)它们的迭代是独立的:
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
if(asubsref(seed,j) > 0)
asubsref(bin,j) = asubsref(bin,j) + 1;
asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
}
}
然后交换最里面和最外面的循环
for(j=0; j<n; j++)
{
for(i=0; i<n; i++)
{
if(asubsref(seed,j) > 0)
asubsref(bin,j) = asubsref(bin,j) + 1;
asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
}
}
现在很明显,以下代码应该可以正常工作
#pragma omp parallel for (private i)
for(j=0; j<n; j++)
{
for(i=0; i<n; i++)
{
if(asubsref(seed,j) > 0)
asubsref(bin,j) = asubsref(bin,j) + 1;
asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
}
}
虽然分裂循环明显打破了不变量。