我知道这个和这个,但我再次问,因为第一个链接现在已经很老了,第二个链接似乎没有得出结论性的答案。有没有达成共识?
我的问题很简单:
我有一个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
将 100000 个粒子放在一个边 100 的盒子中:
$ 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 上完成的。此外,并发的优势似乎随着规模的增加而减少。