2012-10-30 45 views
2

我有以下for循環。當我打開類型數組時,代碼不會進行矢量化。當我將類型修復爲'1'時,gcc執行初始化矢量化矢量化。有沒有人有任何建議來觸發某種矢量化?內部if語句殺死向量化

#define type(M,N) type[(M)*sizeX + (N)] 
for (int i = 0; i < sizeY - 1; i++) 
{ 
    for (int j = 0; j < sizeX - 1; j++) 
    { 
     const int id = type(i, j); 
     //const int id = 1; //vectorizes 
     const float A = this->A[id]; 
     const float B = this->B[id]; 
     a(i, j) = A * a(i, j) + B * (b(i, j) - b(i + 1, j))*(p[i]); 
    } 
} 

從GCC近似誤差4.7.1

45: not vectorized: not suitable for gather A_26 = *D.14145_25; 

編輯1

所有陣列的存儲作爲指針,與定義限制關鍵字作爲一些類的成員。

編輯2

是否有東西,如果 'type' 小我能做什麼?

編輯3

小型裝置8

+0

那麼,type()是什麼? – Mysticial

+0

type是類中使用__restrict__關鍵字定義的整數數組(如同所有數組一樣) – Mikhail

+0

您正在像函數一樣調用'type()'。你能展示那個函數的定義嗎? – Mysticial

回答

4

所不同的是存儲器存取。

id = 1時,下面的數組加載成爲單個元素矢量廣播。

const float A = this->A[id]; 
const float B = this->B[id]; 

但是,當id = type[(i)*sizeX + (k)],存儲器訪問是跨步(不連續)。

  1. 連續的內存塊:

    矢量加載和存儲在SSE和AVX只能上完成。

  2. 或從廣播到整個矢量的單個元素。

它們無法處理從內存的不同部分加載每個向量元素的內存訪問。

AVX2將支持這種「收集/分散」指令。


爲了解決編輯:

如果type(i, j)i名不是零,內存訪問仍然跨進。所以這將很難矢量化。 (我說「困難」而不是「不可能」,因爲編譯時間可能會縮短很長的一步 - 儘管效率降低了。)

您在這裏遇到的核心問題是您正在迭代行的矩陣。如果沒有收集/分散支持,這不僅無法實現矢量化,而且對緩存也不利。

我不確定您要完成什麼任務,但您可能需要考慮採用不同的數據佈局以獲得最佳性能。

+0

5:38 AM在這裏。我應該睡一會兒... – Mysticial

+0

+1一如既往的優秀分析。 –

+0

re:不同的數據佈局 - 不是MxN「矩陣」,您可以使用尺寸爲(M * N)的一維數組並使用mod和div操作對其進行操作,從而基本上爲duff的設備創建基礎優化得相當好 – technosaurus