2011-12-09 51 views
0

對不起,我剛開始學習OpenMP,所以我有點困惑。 我正在分析我的分子動力學模擬和代碼的一部分,我試圖找到水分子(或離子)和蛋白質之間的最近距離。這是非常耗時的部分,因爲我有大約50萬個原子和大約25000個幀。通過單個CPU需要1周(對於一組計算,不僅是距離)。OpenMP for loop不會給出正確的結果

我改變了這部分代碼通過的OpenMP並行,這是非常快,但有一個小錯誤;與單個CPU代碼相比,90%的結果(距離)是正確的,10%是錯誤的。 這是我的代碼的一部分,它計算的最近距離:

... 
    for (i=0; i< number of frames(25000)) 
    ... 
    // XP,YP,ZP protein coordinates; malloc allocation in the code 
    // XI,YI,ZI Sodium molecule coordinates; malloc allocation 
    // LX,LY,LZ the dimension of simulation box, malloc allocation 
    // dimI defined as a temporary closest distance, filled with very large constant, 
    // malloc allocation 
    // NSOD number of Sodium molecules 
    // rhos keeping the closest distance for each Sodium for each frame. 
    … 
    ...int l=0,kk=0; 
#pragma omp parallel for shared(XI,YI,ZI,XP,YP,ZP,LX,LY,LZ,qq,dimI,distI,rhos,xmin,ymin,zmin,i) private(kk,l) 
     for (l=0; l < NSOD; l++){ 
     // this part relocates every thing inside a box with dimension LX*LY*LZ. xmin, ymin and zmin are the boundaries of the box. 
     if (XI[l]!=0.0 || YI[l]!=0.0 || ZI[l]!=0.0){ 
      if (XI[l] < xmin) XI[l] += ceil((xmin - XI[l])/LX[i-1]) * LX[i-1]; 
      if (XI[l] > xmax) XI[l] -= ceil((XI[l] - xmax)/LX[i-1]) * LX[i-1]; 
      if (YI[l] < ymin) YI[l] += ceil((ymin - YI[l])/LY[i-1]) * LY[i-1]; 
      if (YI[l] > ymax) YI[l] -= ceil((YI[l] - ymax)/LY[i-1]) * LY[i-1]; 
      if (ZI[l] < zmin) ZI[l] += ceil((zmin - ZI[l])/LZ[i-1]) * LZ[i-1]; 
      if (ZI[l] > zmax) ZI[l] -= ceil((ZI[l] - zmax)/LZ[i-1]) * LZ[i-1]; 
     } 
     for (kk=0; kk<NP; kk++){ 

     if ((XP[kk]!=0. || YP[kk]!=0. || ZP[kk]!=0.) ){ 
      distI[l] = sqrt((XI[l]-XP[kk])*(XI[l]-XP[kk]) + (YI[l]-YP[kk])*(YI[l]-YP[kk]) + (ZI[l]-ZP[kk])*(ZI[l]-ZP[kk])); 
      if (distI[l] < dimI[l]) { 
       dimI[l] = distI[l]; 
      } 
     } 
     } 
     distI[l] = dimI[l]; 
     rhos[qq][l] = dimI[l]; 

} 的#pragma OMP屏障 ...

你能告訴我什麼是錯與並行後,我的代碼?爲什麼只在某些情況下給出了錯誤的答案,而不是所有的情況?我非常感謝您的意見和建議。我在linux上使用gcc。 非常感謝你,

乾杯, 阿拉什

回答

2

當浮動處理點也可能不是一個好主意,有

if (XI[l]!=0.0 || YI[l]!=0.0 || ZI[l]!=0.0){ 

而應該用小量比較(是一些非常小的號碼)

if (fabs(XI[l]) > epsilon || ... 

否則可能會導致問題。

+0

嗨安德斯,我會申請後你的建議,謝謝,阿拉什 – Arash

1

除了安德斯的答案。

比雷亞爾數學運算,浮點運算其他是由於舍入誤差不相關聯。 OpenMp會改變循環的評估順序,因此結果通常會稍有不同。您必須執行敏感性分析,以確定您希望得到的結果的精度,以及查看您使用(或不使用)OpenMP計算的內容是否在可容忍的範圍內。

數字是一門藝術。

+0

喜延之後的結果,感謝您的回覆。我按照Anders的建議改變了條件,但結果是一樣的。關於精度,例如,串行代碼計算第一原子的距離,例如2.57埃(絕對精確),但並行代碼給出了300.12埃!它表明並行代碼的問題來自計算最近距離的內部循環,特別是這條線「if(distI [l] Arash

+0

這部分事實上是奇怪的,它應該做什麼?就像現在一樣,它計算某些值的最小值(那些滿足條件的'kk')?特別是如果沒有'kk'符合條件'distI [l]'不會改變。我猜想在這種情況下應該設置爲「0.0」或「epsilon」。 –

+0

您好Jens,請閱讀我的新評論,我找不到原因。皮疹 – Arash

0

我的問題已被偶然解決,雖然我討厭這種盲目解決問題;因此我找不到任何解釋。 正如我所提到的,我應該找到蛋白質 - 水,蛋白質 - 鈉和蛋白質 - 氯化物之間的最近距離。爲了完成這項工作,我需要一個臨時浮點變量來比較新距離和前一個距離,如果它較小,則替換最小距離。我認爲,因爲我要在不同的線程上運行它,所以在我的代碼中爲此比較定義一維浮點數組更安全。我定義了一維浮點數組dimI[l],並在初始化期間用一個非常大的浮點數填充它。

我在我的代碼試圖共享和專用變量的無數組合的openmp命令和最後我取代這個1D陣列與普通浮法並將它定義爲一個專用變量;令人驚訝的是它解決了這個問題,現在它完美地工作。

爲什麼1D數組不能用作臨時變量?看起來定義一維數組更安全;無論線程數,如下,其中kk=0..NSOD是私有的,其他的都共享變量

Thread 0   T1     T2      
    l=0 ..10   l=11..20   l=21..30    
kk1=0..NSOD  kk2=0..NSOD   kk3=0..NSOD 
XI[l],XP[kk1] XI[l] ,XP[kk2]  XI[l],XP[kk3] 
    distI[l]   distI[l]   distI[l] 
    dimI[l]   dimI[l]    dimI[l] 

有什麼不對上述方法?

乾杯, 阿拉什

相關問題