我正在尝试使用OpenMP 4.0 simd
功能对嵌套循环进行矢量化,但我担心我做错了。我的循环看起来像这样:
do iy = iyfirst, iylast
do ix = ixfirst, ixlast
!$omp simd
do iz = izfirst, izlast
dudx(iz,ix,iy) = ax(1)*( u(iz,ix,iy) - u(iz,ix-1,iy) )
do ishift = 2, ophalf
dudx(iz,ix,iy) = dudx(iz,ix,iy) + ax(ishift)*( u(iz,ix+ishift-1,iy) - u(iz,ix-ishift,iy) )
enddo
dudx(iz,ix,iy) = dudx(iz,ix,iy)*buoy_x(iz,ix,iy)
enddo
!$omp end simd
enddo
enddo
请注意,ophalf
是一个小整数,通常为2或4,因此对iz
循环进行矢量化而不是最内层循环是有意义的。
我的问题是:我是否必须将ishift
标记为私有变量?
在标准的OpenMP parallel do
循环中,您确实需要private(ishift)
来确保其他线程不会踩踏彼此的数据。然而,当我改为将第一行重写为!$omp simd private(ishift)
时,我得到了ifort编译错误:
错误#8592:在SIMD区域内,不能在PRIVATE SIMD子句中指定DO循环控制变量。 [ISHIFT]
在网上看,我无法找到这个问题的任何成功解决方案。在我看来ishift
应该是私有的,但编译器不允许它。是否内部循环变量自动被强制为私有?
后续问题:稍后,当我在omp parallel do
循环周围添加iy
时,我应该在private(ishift)
指令中包含omp parallel do
子句,{{ 1}}指令,或两者兼而有之?
感谢您的任何澄清。
答案 0 :(得分:0)
关于SIMD的私有子句实质上意味着ishift的值对于SIMD寄存器中的每个SIMD通道是私有的。当我们矢量化最内层循环时,这是正确的,因为ishift是循环归纳变量。但是当你进行外循环矢量化时,每个SIMD通道对于iz循环索引将具有不同的值,但是给定循环索引iz,ishift仍然可以具有从2到ophalf的值。所以它没有资格在SIMD上下文中使用私有子句。
当谈到多个线程时,你需要ishift的副本,这样一个增加这个变量的线程就不会让其他线程跳过那个迭代。因此私有子句对于omp并行do上下文中的ishift是有意义的。如果内部循环完全展开并且为循环索引为iz的循环进行矢量化,那么检查底层代码生成将会很有趣。