2015-12-14 188 views
4

我想要使用OpenMP 4.0的simd功能矢量化嵌套循环,但恐怕我做错了。我的循环看起来像这样:OpenMP 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: Within a SIMD region, a DO-loop control-variable must not be specified in a PRIVATE SIMD clause. [ISHIFT]

寻找网上,我无法找到这个问题的任何成功解决。在我看来,ishift应该是私有的,但编译器不允许它。内循环变量是否被自动强制为私有?

后续问题:后来,当我添加omp parallel do围绕iy循环,我应该包括在omp parallel do指令一个private(ishift)子句,omp simd指令,或两者兼而有之?

感谢您的任何澄清。

+2

展开常规情况下的专业化循环。 – Jeff

+2

简单的'omp simd'构造不是多线程的,它们是矢量化的,不同的。你保持循环的主体,但你用标量指令替换标量指令。如果你试图自己写这个矢量化的版本,你会立即看到为什么使私有“ishift”变得毫无意义。 – Gilles

+0

谢谢@Gilles。我已经知道你在说什么了,但是强迫自己试着写出来,真的让我更好地理解它,并让你的观点变得非常明显。你是对的 - 'ishift'变量不应该是私有的。此外,我无法想象一个环路迭代器应该被设置为私有的情况,所以ifort错误对我来说似乎是合理的。干杯。 – NoseKnowsAll

回答

0

涉及到SIMD的私有条款实质上意味着SIMD寄存器中每个SIMD通道的ishift值都是私有的。因为ishift是循环感应变量,所以我们向量化最内层循环时就是这样。但是当你做一个外部循环向量化时,每个SIMD通道对于iz循环索引都会有一个不同的值,但是给定一个循环索引iz,ishift的值仍然可以从2到ophalf。所以它不符合SIMD上下文中的私人条款。

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