Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 我应该何时使用DO CONCURRENT和何时使用OpenMP?_Concurrency_Fortran_Openmp_Simd_Fortran2008 - Fatal编程技术网

Concurrency 我应该何时使用DO CONCURRENT和何时使用OpenMP?

Concurrency 我应该何时使用DO CONCURRENT和何时使用OpenMP?,concurrency,fortran,openmp,simd,fortran2008,Concurrency,Fortran,Openmp,Simd,Fortran2008,我知道和,但我再次问,因为第一个链接现在已经很旧了,而第二个链接似乎没有得出结论性的答案。有没有达成共识 我的问题很简单: 我有一个DO循环,其中的元素可以同时运行。我用哪种方法 下面是在简单立方晶格上生成粒子的代码 npart是粒子数 npart_边和npart_面分别沿边和面 空间是晶格间距 Rx、Ry、Rz是位置阵列 x、 y,z是决定晶格位置的临时变量 请注意,不同之处在于,x、y和z在并发情况下必须是数组,但在OpenMP情况下并非如此,因为它们可以定义为私有 因此,我是否使用do

我知道和,但我再次问,因为第一个链接现在已经很旧了,而第二个链接似乎没有得出结论性的答案。有没有达成共识

我的问题很简单:

我有一个
DO
循环,其中的元素可以同时运行。我用哪种方法

下面是在简单立方晶格上生成粒子的代码

  • npart是粒子数
  • npart_边和npart_面分别沿边和面
  • 空间是晶格间距
  • Rx、Ry、Rz是位置阵列
  • x、 y,z是决定晶格位置的临时变量
请注意,不同之处在于,x、y和z在并发情况下必须是数组,但在OpenMP情况下并非如此,因为它们可以定义为私有

因此,我是否使用
do CONCURRENT
(我从上面的链接中了解到,它使用SIMD):

还是使用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上完成的。而且,并发的优势似乎随着大小的增加而减少。

DO CONCURRENT本身并不做任何并行化。编译器可能决定使用线程或SIMD指令对其进行并行化。对于线程,您通常必须指示它这样做。或者(通常!)它只是将其视为常规DO,如果它将其用于常规DO,则使用SIMD

OpenMP也不仅仅是线程,编译器可以根据需要使用SIMD指令。还有
omp simd
指令,但这只是建议编译器使用simd,可以忽略它

你应该试试看。没有一个明确的答案。即使对于一个给定的编译器,对于所有的编译器也是如此


我的做法是使用OpenMP并尝试确保编译器矢量化(SIMD)。特别是因为我在我的程序中都使用OpenMP。你还需要证明它实际上是有用的。我还不确信。

关于x、y和z在DO并发情况下需要是数组的断言不是语言要求。如何实现并发也在很大程度上取决于编译器的能力——惰性编译器可能只是将其实现为普通的串行循环,而没有任何矢量化或并行化。所以答案是。。。“视情况而定。”@IanH你说这不是语言要求是什么意思?我说它们必须是数组,因为否则,这些操作不能同时进行。另外,我还添加了关于性能的编辑信息。那么现在的问题是什么?一般情况下,并发还是OpenMP?或者如何使这段代码运行得更快?这些都是非常不同的问题。当然,一般的答案是使用更快的方法。@IanH好的,我读过了,现在我明白了。因此,这意味着处理器可以按任意顺序执行迭代,这可能是并发的,也可能不是并发的。这确实是一个不好的命名的例子。仅仅因为我们有一个闪亮的新功能:一些
do concurrent
。我已经添加了您之前请求的信息作为编辑。此外,我确实在代码的其他地方使用了openmp,但在那里,并发性没有帮助。ifort-qparallel请求并行化do concurrent。使用上面给出的选项,将只有simd矢量化,这对于您的问题大小似乎更有效。如果内部循环长度最多为100,将其拆分为线程块将消除simd矢量化的大部分优势。块可以在DO CONCURRENT中使用,以避免为局部变量生成数组。假设您在启用超线程的情况下运行,则需要检查线程数小于默认值的并行性能,设置OMP_PLACES=cores,然后才能得出并行效率太低的结论。几乎没有理由期望do concurrent auto parallel执行与OpenMP不同的操作。@tim18在这个问题下给出更好的评论。这个答案是在细节暴露之前写的,根本没有反映出来。@tim18所以如果我在
DO
循环中放置
,每个迭代的局部变量是独立的?这比制作阵列更有效吗?另外,我为什么要将omp设置为不使用超线程?
$ 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