使用#pragma parallel for shared在OpenMP中并行化嵌套循环

时间:2013-10-05 03:47:05

标签: c multithreading parallel-processing openmp nested-loops

我正在尝试并行化代码。我的代码看起来像这样 -

    #pragma omp parallel private(i,j,k)
    #pragma omp parallel for shared(A)
    for(k=0;k<100;<k++)
     for(i=1;i<1024;<i++)
      for(j=0;j<1024;<j++)
       A[i][j+1]=<< some expression involving elements of A[i-1][j-1] >>

在执行此代码时,我得到了与循环的串行执行不同的结果。 我无法理解我做错了什么。

我也试过了崩溃()

    #pragma omp parallel private(i,j,k)
    #pragma omp parallel for collapse(3) shared(A)
    for(k=0;k<100;<k++)
     for(i=1;i<1024;<i++)
      for(j=0;j<1024;<j++)
       A[i][j+1]=<< some expression involving elements of A[][] >>

我尝试的另一件事是在每个循环之前使用#pragma omp并行而不是collapse()。

我认为这个问题是数据依赖性。知道如何在数据依赖的情况下并行化吗?

2 个答案:

答案 0 :(得分:0)

如果这确实是你的用例,只需并行化外部循环k,这应该足以满足你在常见架构上的适度并行性。

如果你想要更多,你必须重新编写你的循环,以便你有一个没有依赖的内部部分。在你的示例中,这是相对容易的,你必须通过“diagonals”(外循环,顺序)进行处理,然后在对角线内部进行独立处理。

for (size_t d=0; d<nDiag(100); ++d) {
   size_t nPoints = somefunction(d);
#pragma omp parallel
   for (size_t p=0; p<nPoints; ++p) {
      size_t x = coX(p, d);
      size_t y = coY(p, d);
      ... your real code ...
   }

}

部分内容可以自动完成,但我不认为这些工具已经很容易在日常OMP中实现。这是一项积极的研究。

另请注意以下内容

  • int对于索引来说很少是一个好主意,特别是如果你访问矩阵。如果你必须自己计算一个条目的绝对位置(你可能在这里看到),这很容易溢出。 int通常是32位宽,其中32个你甚至浪费一个标志。在C中,对象大小使用size_t计算,大多数时间为64位宽,无论如何都是平台设计者选择的正确类型。
  • 将局部变量用于循环索引和其他临时变量,因为您可以看到编写OMP编译指示变得更加容易。地方是并行的关键。通过正确表达来帮助自己和编译器。

答案 1 :(得分:0)

你只是将外部&#k;&#39; for循环。每个并行线程都在执行&#39; i&#39;和&#39; j&#39;循环,他们都写入相同的&#39; A&#39;结果。由于他们在A中读取和写入相同的插槽,因此最终结果将是不确定的。

您的问题并不清楚任何并行性是可能的,因为每个步骤似乎都取决于之前的每一步。