max*_*max 8 parallel-processing fortran openmp
fortran 2008 do concurrent
构造是一个do循环,它告诉编译器没有迭代会影响任何其他迭代.因此可以安全地并行化.
一个有效的例子:
program main
implicit none
integer :: i
integer, dimension(10) :: array
do concurrent( i= 1: 10)
array(i) = i
end do
end program main
Run Code Online (Sandbox Code Playgroud)
迭代可以按任何顺序完成.你可以在这里阅读更多相关信息.
据我所知,gfortran不会自动并行化这些do concurrent
循环,而我记得有关gfortran扩散列表的邮件(这里).它只是将它们转换为经典do
循环.
我的问题:你知道一种系统地并行化do concurrent
循环的方法吗?例如,使用系统的 openmp语法?
Hri*_*iev 12
自动完成并不容易.该DO CONCURRENT
构造有一个forall-header,这意味着它可以接受多个循环,索引变量定义和掩码.基本上,你需要更换:
DO CONCURRENT([<type-spec> :: ]<forall-triplet-spec 1>, <forall-triplet-spec 2>, ...[, <scalar-mask-expression>])
<block>
END DO
Run Code Online (Sandbox Code Playgroud)
有:
[BLOCK
<type-spec> :: <indexes>]
!$omp parallel do
DO <forall-triplet-spec 1>
DO <forall-triplet-spec 2>
...
[IF (<scalar-mask-expression>) THEN]
<block>
[END IF]
...
END DO
END DO
!$omp end parallel do
[END BLOCK]
Run Code Online (Sandbox Code Playgroud)
(方括号中的东西是可选的,基于forall-header中相应部分的存在)
请注意,这不如使用<iters 1>*<iters 2>*...
独立迭代并行化一个大循环那样有效,这DO CONCURRENT
是预期的.另请注意,forall-header允许使用类型规范,允许在头文件中定义循环索引,并且您需要在BLOCK ... END BLOCK
构造中包围整个内容以保留语义.您还需要检查forall-header -expr是否存在于forall-header的末尾,如果存在,您还应该将其IF ... END IF
放在最里面的循环中.
如果您只在主体内部进行数组赋值,那么DO CONCURRENT
您也可以将其转换为FORALL
并使用workshare
OpenMP指令.它会比上面容易得多.
DO CONCURRENT <forall-header>
<block>
END DO
Run Code Online (Sandbox Code Playgroud)
会成为:
!$omp parallel workshare
FORALL <forall-header>
<block>
END FORALL
!$omp end parallel workshare
Run Code Online (Sandbox Code Playgroud)
鉴于以上所有,我能想到的唯一系统方法是系统地浏览您的源代码,根据forall-header和循环体的内容,使用上述转换结构中的一个来搜索DO CONCURRENT
并系统地替换它.
编辑:workshare
目前不鼓励使用OpenMP 指令.事实证明,至少英特尔Fortran编译器和GCC序列化FORALL
语句和OpenMP workshare
指令内部的构造通过single
在编译期间用OpenMP 指令包围它们而不会带来任何加速.其他编译器可能会以不同的方式实现它,但如果要实现便携式性能,最好避免使用它.
归档时间: |
|
查看次数: |
4807 次 |
最近记录: |