0
的奇怪的複製行爲實行矢量編程。 但是,我遇到了數組賦值的奇怪複製行爲。我使用英特爾Cilk的加數組符號英特爾Cilk的加數組符號
要解決的問題是平行前綴。 D輸入,P輸出。
//錯誤結果代碼。測試Intel icc 14.0.2。
void vec_prefix(int n, int D[n], int P[n]) {
P[0:n] = D[0:n]; //initial copy
int bound=1;
int * Buf1 = _mm_malloc(n*sizeof(int), 16);
int * Buf2 = _mm_malloc(n*sizeof(int), 16);
while(bound<n){
Buf1[0:n-bound] = P[0:n-bound];
Buf2[0:n-bound] = P[bound:n-bound];
//printf("WHY??\n"); //Add this fence, the result will be correct.
P[bound:n-bound] = Buf1[0:n-bound] + Buf2[0:n-bound];
bound<<=1;
}
_mm_free(Buf1); _mm_free(Buf2);
}
如果我刪除了「printf」這一行的註釋,結果是正確的。否則,錯了。 但是,如果所有副本都遵循英特爾文檔中的說明,則代碼應該是正確的。
看來,如果沒有這樣的內存圍欄,前兩行BUF1/Buf2中複製沒有完成,而添加操作後使用了一些不穩定的價值。 或者,編譯器優化器只使用拷貝傳播,以除去複製和創建 「P [約束:N-結合] = P [0:N-綁定] + P [約束:N-結合]」。這在英特爾的文檔中沒有定義。
//正確結果代碼
void vec_prefix(int n, int D[n], int P[n]) {
P[0:n] = D[0:n]; //initial copy
int bound=1;
int * Buf1 = _mm_malloc(n*sizeof(int), 16);
while(bound<n){
//direct copy part
Buf1[0:bound] = P[0:bound];
//add part
Buf1[bound:n-bound] = P[bound:n-bound] + P[0:n-bound];
//copy back
P[0:n] = Buf1[0:n];
bound<<=1;
}
_mm_free(Buf1);
}
參考:英特爾文檔
- http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011Update/compiler_c/optaps/common/optaps_par_cean_prog.htm
- https://www.cilkplus.org/tutorial-array-notation
謝謝您的幫助! – hwang