如何确保我的Fortran FORALL构造被并行化?

时间:2010-09-05 21:27:32

标签: parallel-processing fortran forall

我已经获得了一个表示金属板表面温度点的二维矩阵。基质(板)的边缘保持恒定在20摄氏度,并且在一个预定点处存在100摄氏度的恒定热源。所有其他网格点最初设置为50摄氏度。

我的目标是通过对周围的四个网格点(i + 1,i-1,j + 1,j-1)进行迭代平均来获取所有内部网格点并计算其稳态温度,直到达到收敛(迭代之间的变化小于0.02摄氏度。)

据我所知,迭代网格点的顺序无关紧要。

对我而言,这听起来是调用Fortran FORALL构造并探索并行化乐趣的好时机。

如何确保代码确实是并行化的?

例如,我可以在我的单核PowerBook G4上编译它,我预计由于并行化,速度没有提高。但是如果我在双核AMD Opteron上编译,我会认为FORALL结构可以被利用。

或者,有没有办法衡量程序的有效并行化?

更新

回应M.S.B的问题,这是与gfortran版本4.4.0。 gfortran是否支持自动多线程?

令人遗憾的是,FORALL结构已被淘汰,我想,那就是自动向量化。

也许这对于一个单独的问题是最好的,但自动矢量化如何工作?编译器是否能够检测到循环中只使用纯函数或子例程?

3 个答案:

答案 0 :(得分:7)

FORALL是赋值构造,而不是循环构造。 FORALL的语义表明FORALL中每个赋值的右侧表达式(RHS)在被分配到左侧(LHS)之前完全被评估。无论RHS的操作有多复杂,包括RHS和LHS重叠的情况,都必须这样做。

大多数编译器都在优化FORALL,因为它很难优化,因为它不常用。最简单的实现是简单地为RHS分配一个临时表,计算表达式并将其存储在临时表中,然后将结果复制到LHS中。分配和释放此临时文件可能会使您的代码运行得非常慢。编译器很难自动确定何时可以在没有临时的情况下评估RHS;大多数编译器都没有尝试这样做。嵌套的DO循环变得更容易分析和优化。

对于某些编译器,您可以通过将FORALL与OpenMP“workshare”指令一起包含并使用启用OpenMP所需的任何标志进行编译来并行化RHS的评估,如下所示:

!$omp parallel workshare
FORALL (i=,j=,...)
    <assignment>
END FORALL
!$omp end parallel

gfortran -fopenmp blah.f90 -o blah

请注意,不需要兼容的OpenMP实现(至少包括旧版本的gfortran)来并行评估RHS;实现可以接受评估RHS,就好像它包含在OpenMP“单一”指令中一样。另请注意,“工作共享”可能不会消除RHS分配的临时工作。例如,在Mac OS X上使用旧版本的IBM Fortran编译器就是这种情况。

答案 1 :(得分:6)

如果您使用英特尔Fortran编译器,则可以使用命令行开关打开/增加编译器的详细级别以进行并行化/矢量化。这样在编译/链接期间,您将显示如下内容:

FORALL loop at line X in file Y has been vectorized

我承认自上次使用它以来已经过了几年,因此编译器消息实际上可能看起来非常不同,但这是基本的想法。

答案 2 :(得分:3)

最好的方法是测量计算的时钟时间。尝试使用和不使用并行代码。如果时钟时间减少,那么您的并行代码正在运行。在代码块之前和之后调用的Fortran内部system_clock将为您提供时钟时间。内部cpu_time将为您提供cpu时间,当运行多线程中的代码由于开销而可能会增加。

传说是FORALL并不像引入语言时那样有用 - 它更像是一个初始化构造。编译器同样善于优化常规循环。

Fortran编译器实现真正的并行处理的能力各不相同,而没有明确指定,例如使用OpenMP或MPI。你使用什么编译器?

为了获得自动多线程,我使用了ifort。手动,我使用过OpenMP。使用这两种方法,您可以使用和不使用并行化来编译程序并测量差异。