我知道这个和这个,但是我再次询问,因为第一个链接已经很旧了,第二个链接似乎没有得出确定的答案。是否有任何共识发展?
我的问题很简单:
我有一个DO
循环,其中的元素可能被并发运行。我应该使用哪种方法?
下面是在简单立方晶格上生成粒子的代码。
- npart是粒子数量
- npart_edge和npart_face分别沿边缘和面
- space是晶格间距
- Rx,Ry,Rz是位置数组
- x,y,z是用于确定晶格上位置的临时变量
请注意,当使用CONCURRENT的情况下,x,y和z必须是数组,但在OpenMP案例中不需要,因为它们可以定义为PRIVATE。
所以我应该使用DO CONCURRENT
(根据上面的链接,它使用SIMD):
DO CONCURRENT (i = 1, npart)
x(i) = MODULO(i-1, npart_edge)
Rx(i) = space*x(i)
y(i) = MODULO( ( (i-1) / npart_edge ), npart_edge)
Ry(i) = space*y(i)
z(i) = (i-1) / npart_face
Rz(i) = space*z(i)
END DO
我应该使用OpenMP吗?
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(x,y,z)
!$OMP DO
DO i = 1, npart
x = MODULO(i-1, npart_edge)
Rx(i) = space*x
y = MODULO( ( (i-1) / npart_edge ), npart_edge)
Ry(i) = space*y
z = (i-1) / npart_face
Rz(i) = space*z
END DO
!$OMP END DO
!$OMP END PARALLEL
我的测试:
将64个粒子放置在边长为10的盒子中:
$ ifort -qopenmp -real-size 64 omp.f90
$ ./a.out
CPU time = 6.870000000000001E-003
Real time = 3.600000000000000E-003
$ ifort -real-size 64 concurrent.f90
$ ./a.out
CPU time = 6.699999999999979E-005
Real time = 0.000000000000000E+000
在一个边长为100的盒子中放置100000个粒子:
$ ifort -qopenmp -real-size 64 omp.f90
$ ./a.out
CPU time = 8.213300000000000E-002
Real time = 1.280000000000000E-002
$ ifort -real-size 64 concurrent.f90
$ ./a.out
CPU time = 2.385000000000000E-003
Real time = 2.400000000000000E-003
使用
DO CONCURRENT
结构似乎能够提高至少一个数量级的性能。这是在i7-4790K上完成的。此外,并发的优势似乎随着规模的增加而减少。
do concurrent
的一些文档。 - francescalus