OpenMP嵌套循环的SIMD向量化

4

我正在尝试使用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编译错误:

error #8592:在SIMD区域内,DO-loop控制变量不能在PRIVATE SIMD子句中指定。[ISHIFT]

在线上搜索后,我没有找到任何成功解决这个问题的方法。对我来说,ishift应该是私有的,但编译器不允许它。内部循环变量是否自动强制为私有?
后续问题:稍后,当我在iy循环周围添加omp parallel do时,我应该在omp parallel do指令、omp simd指令或两者都包含private(ishift)子句吗?
感谢任何澄清。

2
为常见情况在专业化中展开该循环。 - Jeff Hammond
2
简单的omp simd结构不是多线程的,而是矢量化的,这是不同的。您保留循环体,但将标量指令替换为矢量指令。如果您尝试手动编写此矢量化版本,您会立即看到为什么使ishift私有化没有太大意义。 - Gilles
谢谢@Gilles。我已经知道你说的了,但是强迫自己尝试写出来确实让我更好地理解了它,并且使你的观点变得非常明显。你是对的 - ishift变量不应该被设为私有。此外,我想不出一个情况,循环迭代器应该被设为私有,所以ifort错误对我来说似乎是合理的。干杯。 - NoseKnowsAll
我看到我一开始理解错了问题。我以为你在iy循环周围有omp do private(ishift)。在这种情况下,私有变量不应该是一个问题。 - Vladimir F Героям слава
1个回答

0

在 SIMD 中,私有条款基本上意味着 ishift 的值对于 SIMD 寄存器内的每个 SIMD 轨道都是私有的。当我们向量化最内层循环时,这是正确的,因为 ishift 是循环归纳变量。但是,当你进行外部循环向量化时,每个 SIMD 轨道将具有不同的 iz 循环索引值,但是对于给定的循环索引 iz,ishift 仍然可以具有从2到 ophalf 的值。因此,在 SIMD 上下文中它不能符合私有条款。

当涉及到多个线程时,您需要 ishift 的副本,以便一个线程递增该变量不会使其他线程跳过该迭代。因此,在 omp parallel do 上下文中,私有条款对于 ishift 是有意义的。如果内部循环针对具有循环索引 iz 的循环完全展开和向量化,检查底层代码生成将非常有趣。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接