【发布时间】:2015-09-10 15:54:12
【问题描述】:
在我尝试移植到 OpenMP 的代码中,我有一个嵌套在外循环中的并行循环。根据外部循环的迭代,我希望一个特定的数组是shared 或reduction(+)。有没有办法在 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 行长,嵌套了四层。分支基于第二个循环的状态发生,甚至可能不会发生在基于提供给代码的输入的任何给定运行中。删除外部循环比仅使用两个数组更痛苦。