2017-10-08 45 views
1

我有一個任務,並正在給下面的循環:解釋迴路如何進行矢量

for (i = 0; i < 7030; i++) { 
    a[7031 * i + 703] = b[i] * c[i];  // S1 
    d[i] = a[7031 * i + 703 * 7030] + e; // S2 
} 

首先,有人問我通過使用GCD測試和班納吉的不完整和不完整的測試,以確定數據的依賴性。

  • 從GCD測試中我得出結論,在這個循環中沒有依賴關係。
  • 從Banerjee的不完整測試我確定存在依賴關係。
  • 從Banerjee的完整測試中,我確定了循環中存在True和Anit-Dependency。

GCD Test與Banerjee's Test之間的結果與GCD Test之間的差異是否較弱/較不準確?如果是這樣,我是否應該始終接受Banerjee完整測試的結果?其次,我被要求解釋循環如何被矢量化並描述由循環實現的矢量操作。

我可以簡單地說,你可以將S1和S2分成兩個單獨的for循環,包含S1的循環在包含S2的循環之前全部執行?

for (i = 0; i < 7030; i++) { 
    a[7031 * i + 703] = b[i] * c[i]; 
} 

for (i = 0; i < 7030; i++) { 
    d[i] = a[7031 * i + 703 * 7030] + e; 
} 

在「描述循環實現什麼向量操作」方面,我迷失在這裏寫什麼。

回答

1

因爲這是一個任務,你可能想了解矢量化過程,我不提供可以編譯的源代碼(你應該在我的答案後做一些編碼)。希望你能自己解決。

//The loop counter should be suitable for Vectorization Factor (VF) 
//In this case VF=4 (assume your processor has 128-bit SIMD register and data are 32-bit. 
//1757×4 = 7028 --> you will have 2 values that can not be put in vectos or you must pad the array to fit the vector. 

for (i = 0; i < 7028; i+=4) { 
    a[7031 * i + 703] = b[i] * c[i]; 
    a[7031 * (i+1) + 703] = b[i+1] * c[i+1]; 
    a[7031 * (i+2) + 703] = b[i+2] * c[i+2]; 
    a[7031 * (i+3) + 703] = b[i+3] * c[i+3]; 
} 
a[7031 * i + 703] = b[i] * c[i]; 
i++; 
a[7031 * i + 703] = b[i] * c[i]; 

//vec_b = (b[i], b[i+1], b[i+2], b[i+3]); // are adjacent -> thus can be loaded 
//vec_c = (c[i], c[i+1], c[i+2], c[i+3]); // are adjacent -> thus can be loaded 
//index = 7031*i + 703 
//vec_a = (a[index], a[index + 7031], a[index + 7031*2], a[index + 7031*3]; //not adjacent! 

vec_b = __mm_loadu_ps(&b[i]);負載從相鄰元件您ASLO可以使用從相鄰元件intrinsic instruction這樣載荷加載指令的向量到向量vec_c。但關鍵是你應該將數據存儲到非連續地址。如果處理器支持AVX-512,則可以使用scatter指令將矢量存儲到非連續地址。 如果您沒有scatter說明,您可能需要提取元素並將其放入不同的目標地址。 _mm_extract_epi32_mm_cvtss_f32和移位等

for (i = 0; i < 7030; i++) { 
    d[i] = a[7031 * i + 703 * 7030] + e; 
} 

需要再次進行矢量化,你需要了解數據的地方:

Index = 7031 * i + 703 * 7030 
for (i = 0; i < 7028; i+=4) { 
    d[i] = a[Index] + e; 
    d[i+1] = a[Index + 7031] + e; 
    d[i+2] = a[Index + 7031*2] + e; 
    d[i+3] = a[Index + 7031*3] + e; 
} 
//extra computations for i = 7028, 7029; 
//vec_a = (a[Index], a[Index + 7031], a[Index + 7031*2], a[Index + 7031*3]) 
//vec_a can be loaded with _mm_set_ps (a3, a2, a1, a0), etc but `gather` instruction is also use full to load from different addresses. 
//vec_e = (e, e, e, e) : you can use _mm_set_ps1, _mm_set1... 

最後如何乘或補充的嗎?容易使用向量運算

vec_a = _mm_mul_ps(vec_b, vec_c); 
vec_d = _mm_add_ps(vec_a, vec_e); 

以及如何存儲,以繼續把一個向量?

_mm_store_ps(d[i],vec_d); //i=i+4 for the next store I mean your loop counter must be appropriate. 

因此,矢量化的循環中,您可以使用內部函數作爲一個明確的量化,也可以依靠隱性量化,如使用gcc /鐺在-O3優化級別或適當標誌啓用gcc -ftree-vectorize -ftree-slp-vectorize