2013-07-26 18 views
0

我想向量化下面的循環在C:如何克服「載體的依賴存在」在ICC

for(k = 0; k < SysData->numOfClaGen; k++) 
      A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]); 

其中,有變量之間沒有別名ind0是一個常數。沒有其他指針(AB)指向ind0,因此ind0在整個循環中保持不變。

當我用icc編譯代碼時,它說這個循環由於可能的向量依賴性而不能被矢量化。這裏是消息:

loop was not vectorized: existence of vector dependence. 

我縮小了問題,發現用常數代替ind0解決了這個問題。所以,我認爲icc認爲A可能指向ind0,因此,ind0可能會改變。

我想知道我該如何幫助編譯器知道向量化這種循環是安全的。

在此先感謝您的幫助。

回答

2

在for循環之前加上#pragma ivdep,它指示編譯器忽略假定的矢量依賴關係。

#pragma ivdep 
for(k = 0; k < SysData->numOfClaGen; k++) 
      A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]); 

約ivdep更多信息,請參閱icc doc

1

爲指針使用restrict修改的斷言編譯器沒有走樣。該關鍵字在C99中引入。 C++不支持它,但許多C++編譯器支持__restrict作爲等效的專有擴展。使用英特爾編譯器,必須通過添加命令行標誌-restrict(Linux)或/Qrestrict(Windows)來啓用restrict。在你的代碼的以下版本使用英特爾編譯器版本13.1.3.198時所需的循環被矢量:

#include <math.h> 

struct bar { 
    int numOfClaGen; 
}; 

void foo (double * restrict A, 
      const double * restrict B, 
      const double * restrict x1, 
      const struct bar * restrict SysData, 
      const int ind0) 
{ 
    int k; 
    for (k = 0; k < SysData->numOfClaGen; k++) { 
     A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]); 
    } 
} 

調用編譯如下(在64位Windows系統上)

icl /c /Ox /QxHost /Qrestrict /Qvec-report2 vectorize.c 

編譯器報告

vectorize.c(14): (col. 5) remark: LOOP WAS VECTORIZED. 
0

ICC改爲一年前設定-ansi別名爲Linux和Mac默認。對於Windows,此默認值不能計入,因爲它與Microsoft使用情況相沖突。這個選項相當於gcc -fstrict-aliasing,自從gcc 3.0以來它一直是默認的。我認爲設置這個選項比設置ivdep restrict或simd這樣一個有限的問題好得多。 儘管沒有很好的文檔記錄,但icc將__restrict與gcc相同,並且不要求限制或C99選項來接受它。原則上,它只適用於被修改的對象(上例中的A [])。 奇怪的是,__restrict對於MSVC++有一個稍微不同的含義。它允許非矢量優化,否則可能會被可能的依賴性阻止,但不啓用矢量化(但它可能適用於當前情況)。

相關問題