2015-10-05 116 views
0

我有我想要與OpenMP並行的循環。當我與gcc -o prog prog.c -lm -fopenmp編譯時,我沒有得到任何錯誤。但是當我執行它時,我得到了segmentation fault(core dumped)。當然來自OpenMP的問題命令,因爲程序的時候我刪除#pragma工程...OpenMP給出(核心轉儲)

這裏是並行循環:

ix = (i-1)%ILIGNE+1; 
iy = (i-1)/ILIGNE+1; 
k = 1; 
# pragma omp parallel for private(j,jx,jy,r,R,voisin) shared(NTOT,k,i,ix,iy) num_threads(2) schedule(auto) 
for(j = 1;j <= NTOT;j++){ 
    if(j != i){ 
    jx = (j-1)%ILIGNE+1; 
    jy = (j-1)/ICOLONE+1; 
    r[k][0] = (jx-ix)*a; 
    r[k][1] = (jy-iy)*a; 
    R[k] = sqrt(pow(r[k][0],2.0)+pow(r[k][1],2.0)); 
    voisin[k] = j; 
    k++; 
    } 
} 

我試圖改變堆棧大小無限制,但它不」解決問題。請告訴我,如果它是關於內存泄漏或競爭條件或其他什麼?並感謝您的幫助

回答

0

我不確定你的代碼是做什麼的,但我確信OpenMP版本是錯誤的。事實上,你在j循環上並行,但算法的核心是圍繞k,這是從ji(這裏沒有提供)。

因此,當您在OpenMP線程中分配j索引時,它們全部從j的不同值開始,但全部來自共享的相同值k。由此,k相當隨機地遞增,並且使用k訪問各個陣列非常可能產生分段錯誤。

此外,如果想要並行化具有任何效果,則不應聲明陣列r,Rvoisinprivate

最後,像這樣的C循環for(j = 1;j <= NTOT;j++)看起來完全可疑我的一個訪問...應該不是那麼寧可for(j = 0;j < NTOT;j++)? (只是提到這一點,因爲k初始值是1,以及...)

底線是,你會從j的價值與k = j<i ? j : j-1可能是更好的定義,而不是試圖增加它裏面的代碼k。 假設所有的休息是正確的,這可能是一個有效的版本:

ix = (i-1)%ILIGNE+1; 
iy = (i-1)/ILIGNE+1; 
# pragma omp parallel for private(j,jx,jy,k) num_threads(2) schedule(auto) 
for(j = 1;j <= NTOT;j++){ 
    if(j != i){ 
    k = j<i ? j : j-1; 
    jx = (j-1)%ILIGNE+1; 
    jy = (j-1)/ICOLONE+1; 
    r[k][0] = (jx-ix)*a; 
    r[k][1] = (jy-iy)*a; 
    R[k] = sqrt(pow(r[k][0],2.0)+pow(r[k][1],2.0)); 
    voisin[k] = j; 
    } 
} 

不過,要小心爲0的C索引大小-1,而不是從1到大小...

+0

感謝吉爾斯。它完成了;) –

+0

它是否工作? – Gilles

+0

是的,它的工作,thanx :) –

1

由於一個側面說明,當你把一個數組私人化時要小心。

如果您將其分配爲靜態數組 int R[5]或類似的東西,那很好,每個線程都有自己的個人副本:)。

如果malloc這些然而 如:

int R = malloc(5*sizeof(int)); 那麼它將作爲一個共享的陣列無論你把它定義爲私有的(這可能會導致不確定的行爲,段錯誤,jibberish陣列中的等)。