2014-09-28 48 views
-3

您能否給我一個循環如何實現向量化的例子?例如,我有以下循環:循環如何被矢量化?可以通過循環實現什麼向量操作

for (i=1; i < N; i++) { 
    a[i] = b[i]*c[i]; 
    d[i] = a[i-1] + 7; 
} 

我知道不應該有矢量化循環之前的任何依賴,但是你展示之後,有沒有什麼相關性。它究竟如何被矢量化,哪些步驟?

+1

這是什麼語言?這可能很明顯,但你仍然在你的問題中指定它。 – Jubobs 2014-09-28 17:48:32

+0

這是錯誤的。假設i = 0,那麼你設置了一個[11] = b [0] * c [0],但是下一個語句你想把d [0]設置爲[4 * N] + 7,顯然, 4 * N]可能還沒有被初始化/分配。所以這個數據依賴性必須先解決。 – 2014-09-28 17:55:45

+0

@Jubobs和DebasishJana,即使沒有指定語言並給出示例不是最好的,但我仍想嘗試理解進一步的矢量化步驟。或者你可以舉一個你自己的例子,並說明如何在假設沒有依賴的情況下完成它。 謝謝 – Mikon 2014-09-28 18:03:16

回答

2

從你的問題來看,我不太清楚你是否在問如何手動向量化矢量化,或者如果你問矢量化編譯器如何做到這一點。因此,我將僅解釋編譯器如何執行,並且如果需要,您可以始終手動重複相同的步驟。讓我們用作爲一個例子向量化到寬度4

原始代碼:

for (i=1; i < N; i++) { 
    a[i] = b[i]*c[i]; 
    d[i] = a[i-1] + 7; 
} 

首先,編譯器需要確定的是,雖然第n次迭代取決於迭代n-1,這是一個虛假的依賴,因爲有沒有數據流依賴性 - a[n]不取決於a[n-1]。一旦這被確定,編譯器可以執行loop fission

for (i=1; i < N; i++) { 
    a[i] = b[i]*c[i]; 
} 
for (i=1; i < N; i++) { 
    d[i] = a[i-1] + 7; 
} 

這兩種現在可以向量化;讓我們把重點放在第一個,但對另一個來說也是一樣的。因此,我們的代碼是:

for (i=1; i < N; i++) { 
    a[i] = b[i]*c[i]; 
} 

對於我們的例子,讓我們假設量化寬度爲4。矢量化的關鍵是loop unrolling。因此,編譯器解開大小4:

int i = 1; 
// Unrolled loop: 
for (; i < N-3; i+=4) { 
    a[i] = b[i] *c[i]; 
    a[i+1] = b[i+1]*c[i+1]; 
    a[i+2] = b[i+2]*c[i+2]; 
    a[i+3] = b[i+3]*c[i+3]; 
} 
// Remainder loop: 
for (; i < N; i++) { 
    a[i] = b[i]*c[i]; 
} 

它現在明顯的是如何向量化 - 編譯器改變在展開循環指令相同的序列到一個單一的向量指令:

int i = 1; 
// Unrolled loop: 
for (; i < N-3; i+=4) { 
    a[i:i+3] = b[i:i+3]*c[i:i+3]; 
} 
// Remainder loop: 
for (; i < N; i++) { 
    a[i] = b[i]*c[i]; 
} 

之後,在編譯器的後期「降低」階段,它將爲該操作分配一個實際指令 - 例如,如果這些是啓用SSE的體系結構上的單精度浮點數組,則它可能會使用mulps

1以簡化的方式,當然。
2記住這種情況下的環路分裂實際上會傷害數據的局部性。
3編譯器實際上並不需要展開,只需要查找重複項 - 這些步驟通常會一起使用。

+0

唯一我不明白你爲什麼把下面的代碼? '//剩餘循環: for(; i Mikon 2014-09-28 20:40:04

+0

@Mikon展開循環時,您需要創建一個餘數循環來處理迭代次數不能被展開寬度整除的情況。 – Oak 2014-09-28 22:48:43