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

Parallel processing 如何确保我的Fortran FORALL构造被并行化?,parallel-processing,fortran,forall,Parallel Processing,Fortran,Forall,我得到了一个2D矩阵,表示金属板表面的温度点。矩阵(板)的边缘在20°C时保持恒定,并且在一个预定义点处存在100°C的恒定热源。所有其他栅格点最初设置为50摄氏度 我的目标是获取所有内部网格点,并通过迭代平均周围四个网格点(i+1、i-1、j+1、j-1)来计算其稳态温度,直到达到收敛(迭代之间的变化小于0.02摄氏度) 据我所知,迭代网格点的顺序是不相关的 对我来说,这听起来是一个调用Fortran进行所有构造并探索并行化乐趣的好时机 如何确保代码确实是并行的 例如,我可以在我的单核Powe

我得到了一个2D矩阵,表示金属板表面的温度点。矩阵(板)的边缘在20°C时保持恒定,并且在一个预定义点处存在100°C的恒定热源。所有其他栅格点最初设置为50摄氏度

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

据我所知,迭代网格点的顺序是不相关的

对我来说,这听起来是一个调用Fortran
进行所有
构造并探索并行化乐趣的好时机

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

例如,我可以在我的单核PowerbookG4上编译它,我预计并行化不会提高速度。但是如果我在双核AMD Opteron上编译,我会假设FORALL构造可以被利用

或者,是否有一种方法来衡量程序的有效并行化

更新

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

值得注意的是,我想,福尔构造已经被后来的自动矢量化所淘汰


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

最好的方法是测量计算的时钟时间。可以尝试使用并行代码,也可以不使用并行代码。如果时钟时间减少,则并行代码正在工作。在代码块前后调用的Fortran内部系统时钟将为您提供时钟时间。固有的cpu_时间将为您提供cpu时间,由于开销,当代码运行多线程时,cpu时间可能会增加

据了解,FORALL并不像引入该语言时所认为的那样有用——它更像是一个初始化构造。编译器同样擅长优化规则循环

Fortran编译器在实现真正的并行处理而不显式指定(例如,使用OpenMP或MPI)方面的能力各不相同。你在用什么编译器


为了实现自动多线程,我使用了ifort。我已经手动使用了OpenMP。使用这两种方法,您可以编译有并行化和无并行化的程序,并测量差异。

如果使用“英特尔Fortran编译器”,您可以使用命令行开关打开/增加编译器的详细级别以进行并行化/矢量化。通过这种方式,在编译/链接过程中,您将看到如下内容:

FORALL loop at line X in file Y has been vectorized

我承认,自从我上次使用它已经有几年了,所以编译器消息实际上看起来可能非常不同,但这是基本思想

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

大多数编译器都喜欢对FORALL进行优化,这既是因为它很难优化,也是因为它不常用。最简单的实现是简单地为RHS分配一个临时变量,计算表达式并将其存储在临时变量中,然后将结果复制到LHS中。分配和取消分配这个临时变量可能会使代码运行非常缓慢。编译器很难自动确定何时可以在没有临时参数的情况下计算RHS;大多数编译器都没有这样做。事实证明,嵌套DO循环更易于分析和优化

对于某些编译器,您可以通过使用OpenMP“workshare”指令封装FORALL并使用启用OpenMP所需的任何标志进行编译,从而并行化RHS的评估,如下所示:

!$omp parallel workshare
FORALL (i=,j=,...)
    <assignment>
END FORALL
!$omp end parallel
$并行工作共享
FORALL(i=,j=,…)
端孔
!$端并联
gfortran-fopenmp blah.f90-o blah


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

通常“矢量化”和“并行化”用于不同的优化。矢量化适用于SSE至SSE4 SIMD Intel指令等指令,这些指令可以在单个处理器上并行执行少量操作。并行化导致多线程代码在多个处理器或内核上运行,从两个到多个。对于自动矢量化或并行化,编译器检查的代码有很多限制。有了OpenMP,程序员必须确保不违反限制。我必须弄到ifort才能看到确切的消息,但这种冗长正是我想要的!即使对于自动矢量化的情况,我也希望知道哪些外观正在并行化,哪些没有并行化,特别是对于我认为应该可以并行化的情况。Hmmm。我从未考虑过RHS的复杂性会影响并行化的可能性。那么,您的观点非常清楚,为什么编译器可能会将赌注押在优化FORALL上