1

我有这样的情况:

#pragma omp parallel for private(i, j, k, val, p, l)

for (i = 0; i < num1; i++)  
    {  
   for (j = 0; j < num2; j++)  
       {
         for (k = 0; k < num3; k++)     
             {  
              val = m[i + j*somenum + k*2]  

              if (val != 0)  
              for (l = start; l <= end; l++)  
                  {  
                    someFunctionThatWritesIntoGlobalArray((i + l), j, k, (someFunctionThatGetsValueFromAnotherArray((i + l), j, k) * val));  
                  }

              }  
         }  

        for (p = 0; p < num4; p++)  
            {  
               m[p] = 0;  
            }    
      }

感谢阅读,呸!好吧,当我对串行实现使用上述(速度快 3 倍)时,我注意到结果(0.999967[omp] 与 1[serial])的差异非常小。现在我知道我在这里犯了一个错误……尤其是循环之间的联系很明显。是否可以使用 omp 部分将其并行化?我尝试了一些选项,例如制作 shared(p) {这样做,我得到了正确的值,如串行形式},但当时没有加速。

任何关于通过大量 for 循环处理 openmp pragma 的一般建议对我来说也很棒!

4

1 回答 1

1

这实际上是对您先前问题的重述或改进,如果您对其进行编辑而不是提出“新”问题,它将对 SOers 有所帮助。仍然 ...

当您编写代码时,OpenMP 将分出最外层循环的迭代,即由语句控制的迭代

for (i = 0; i < num1; i++)

到可用的线程。因此,使用默认循环调度,如果您有 4 个线程,每个线程将执行 1/4 的迭代。这可能意味着线程 0 运行迭代i = 0,1,2,...,线程 1 运行迭代(num1/4)+1, (num1/4)+2,...,依此类推。 如果您是 OpenMP 编程的初学者,您真的必须自己研究循环迭代是如何跨线程分布的。您还必须调查修改循环调度的影响。这是学习并行编程的重要组成部分。

然后 OpenMP 将在每个线程上执行内部循环,因此每个线程将执行由变量控制的循环j,k,l,p。这些不会进一步并行化,您的程序没有实现动态线程管理。

这样做的一个结果是所有线程都将更新数组m中的所有值p。这对我来说看起来不明智。

您写道,串行实现和并行实现的结果之间存在差异。但是你没有具体说明什么结果不同。哪个变量在循环结束时具有不同的值?通常,您不应期望串行和并行程序上的浮点结果完全相等,因为 fp 算术的执行顺序很重要。fp 算术不是真正可交换的,也不是真正的关联性或真正的分配性。在一般情况下,即使是简单的数字相加操作,也不能保证同一程序的串行和并行执行是相同的。

但是,如果不知道您报告的结果是如何计算的,则完全不可能说出您为什么会得到差异。这可能是“正常”行为,也可能是错误。

于 2010-04-21T16:35:15.983 回答