崩溃的特例OpenMP

时间:2015-09-11 19:03:01

标签: fortran openmp

我有一个可能很简单的问题,但是看着我,我找不到任何提出相同问题的问题。我的问题是:下面的OpenMP代码中的collapse子句是否会正确处理内部循环?或者只会在第一个内部循环中崩溃?

!$omp parallel do collapse(2) private(iy, ix, iz)
do iy = 1, ny
    do ix = 1, nx
       ! stuff
    enddo
    do iz = 1, nz
       ! different stuff
    enddo
enddo
!$omp end parallel do

这段代码为我编译,显然显示了并行化的好处。但是,我知道标准说:

  

与循环结构相关的所有循环必须完全嵌套;也就是说,任何两个循环之间都不得有干预代码或任何OpenMP指令。

所以我的直觉反应是OpenMP只折叠了第一个内部循环(ix)。但那么它如何处理第二个内循环(iz)?

我显然正在尝试代码执行以下操作,但以这种方式编写代码更加丑陋和冗长:

!$omp parallel private(iy, ix, iz)
!$omp do collapse(2)
do iy = 1, ny
    do ix = 1, nx
       ! stuff
    enddo
enddo
!$omp end do nowait

!$omp do collapse(2)
do iy = 1, ny
    do iz = 1, nz
       ! different stuff
    enddo
enddo
!$omp end do nowait
!$omp end parallel do

1 个答案:

答案 0 :(得分:4)

第一个内部循环是介于外部循环和第二个内部循环之间的代码(据我所知)。如果nznx,则您没有矩形循环。在任何情况下,程序语义都是第一个内循环必须在第二个内循环开始之前完成;它可能执行第二个循环使用的中间计算。 OpenMP 的给定实现可能会执行您想要的操作 - 我没有尝试过这样做。

请注意,第二个示例更改了程序的语义:执行所有ix循环,然后执行所有iz循环,而不是每个ix循环后跟每个iz循环1}}循环使用相同的iy值。如果您可以并行化ix循环,那么这应该是安全的,因为如果ix计算都不依赖于任何iz计算,那么您只能这样做,但如果iz循环将重用相同的数据。因此,正确的语义将取决于在给定循环可以运行之前需要发生什么。 iz循环是否需要ix循环首先运行iy的相同值?如果没有,您可以使用嵌套并行性。

关于循环折叠的注意事项:循环折叠通常意味着您采用嵌套的循环对,例如,

for (i=0;i<100;++i)
  for (j=0;j<50;++j)

将它们变成一个循环,如:

for (ij=0;ij<5000;++ij)

如果您有两个不同索引的内部循环,则无法执行此操作,此外,编译器无法自动更改建议的执行顺序,因为这会更改程序语义。我不确定每个OpenMP实现对这段代码的作用,但我很确定它不会像你希望的那样工作。