2014-02-25 36 views
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); 
} 

參考:英特爾文檔

回答

0

你的代碼看起來正確的給我。不需要「圍欄」。我向英特爾編譯器小組提交了一份內部錯誤報告,並以全部爲例作爲輸入。感謝這個例子。

如果編譯器正常工作,你甚至可以縮短while循環:

while(bound<n){ 
    Buf1[0:n-bound] = P[0:n-bound]; 
    P[bound:n-bound] = Buf1[0:n-bound] + P[bound:n-bound]; 
    bound<<=1; 
} 

第二陣列段分配是好的,因爲對於P的重疊正好。 Alas icc也展示了這個例子的缺陷。

+0

謝謝您的幫助! – hwang