【问题标题】:Conditional shared status in OpenMPOpenMP 中的条件共享状态
【发布时间】:2015-09-10 15:54:12
【问题描述】:

在我尝试移植到 OpenMP 的代码中,我有一个嵌套在外循环中的并行循环。根据外部循环的迭代,我希望一个特定的数组是sharedreduction(+)。有没有办法在 Fortran 中做到这一点?

这是我想要的模型:

do i = 1, 2
  !$omp if(i.eq.1) parallel do reduction(+:foo)
  !$omp if(i.eq.2) parallel do shared(foo)
  do j = 1,j_max
    work on foo
  enddo
  !$omp end parallel
enddo

openMP conditional pragma "if else" 中的讨论表明在执行期间不能修改调度。共享/私有/缩减/等也是如此吗?

一个明显的做法是创建 foo_1 (reduction:+) 和 foo_2 (shared),在 i 上的第一次迭代后将 foo_1 复制到 foo_2,然后在 j 的循环中使用 if 语句来引用正确的数组.但这并不是非常优雅。我希望有更好/更聪明/更清洁的方法来做到这一点。

编辑:对于缺乏想象力的人,这是我的替代方案的伪代码版本

do i = 1, 2
  !$omp parallel do reduction(+:foo_1), shared(foo_2)
  do j = 1,j_max

    if( i .eq. 1 ) then
      work on foo_1
    else
      work on foo_2
    endif

  enddo
  !$omp end parallel

  foo_2 = foo_1
enddo

【问题讨论】:

  • 在您的第一个示例中,您有两个嵌套指令,它们打开两个嵌套的并行部分。我猜你最后需要有两个 !$omp end parallel 指令。
  • 您是否有理由不想删除外部 for 循环并简单地编写两个单独的启用 OMP 的 for 循环?没有任何嵌套,这个问题是微不足道的。
  • 除非你讨厌性能,否则在循环之外进行分支。
  • @NoseKnowsAll 与我实际使用的代码相比,我发布的代码被彻底精简和简化。 OpenMP 部分有 2,000 行长,嵌套了四层。分支基于第二个循环的状态发生,甚至可能不会发生在基于提供给代码的输入的任何给定运行中。删除外部循环比仅使用两个数组更痛苦。

标签: fortran openmp


【解决方案1】:

由于您不介意拥有两个并行区域,因此您可以使用孤立指令 - 我发现这些指令非常适合组织大型 OpenMP 代码的整体结构。我的意思是像

    i = 1
    !$omp parallel shared( i, foo, ... )
    Call do_the_work( i, foo, ... )
    !$omp end parallel
    i = 2
    !$omp parallel shared( i, ... ) reduction( +:foo )
    Call do_the_work( i, foo, ... )
    !$omp end parallel

...

    Subroutine do_the_work( i, foo, ... )
      !$omp do
      do j = 1,j_max
        work on foo
      enddo
    End Subroutine do_the_work

如果平行区域像你说的那么大,它可能无论如何都希望自己处于一个或多个例程中。

【讨论】:

  • 谢谢,但就我的目的而言,使用两个数组比将并行区域分解为子程序更干净。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多