2011-12-09 32 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] 

有什么不对上述方法?

干杯, 阿拉什

相关问题