嵌套循环的OpenMP SIMD矢量化

时间:2015-12-14 17:41:35

标签: fortran openmp vectorization simd

我正在尝试使用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}}指令,或两者兼而有之?

感谢您的任何澄清。

1 个答案:

答案 0 :(得分:0)

关于SIMD的私有子句实质上意味着ishift的值对于SIMD寄存器中的每个SIMD通道是私有的。当我们矢量化最内层循环时,这是正确的,因为ishift是循环归纳变量。但是当你进行外循环矢量化时,每个SIMD通道对于iz循环索引将具有不同的值,但是给定循环索引iz,ishift仍然可以具有从2到ophalf的值。所以它没有资格在SIMD上下文中使用私有子句。

当谈到多个线程时,你需要ishift的副本,这样一个增加这个变量的线程就不会让其他线程跳过那个迭代。因此私有子句对于omp并行do上下文中的ishift是有意义的。如果内部循环完全展开并且为循环索引为iz的循环进行矢量化,那么检查底层代码生成将会很有趣。

相关问题