2015-07-12 61 views
0

我有下面的代码片断OMP更新向量问题

!$OMP PARALLEL PRIVATE(i) 
    do i = inode1,inode2 
    if (mod(CEILING(Rat(1,i)*checkerDivider),2).ne.mod(CEILING(Rat(2,i)*checkerDivider),2)) then 
      H0(i) = H0(i) 
    else 
      H0(i) = H0(i) + onsiteShift 
    endif 
    end do 
    !$OMP END PARALLEL 

onsiteShift等于0.02,和H0(i)是等于0。对于这个例子,我上16个处理器工作。每当我输入else子句时,显然应该将H0(i)的值设置为0.02。但是,在这种情况下,我最终得到0和0.32之间的随机值(步长为0.02)。很显然,我为i的同一个值不止一次地输入了该子句。我也试过使用!$OMP ATOMIC UPDATE,但是最后我得到了0.32(= 16 * 0.02 ...)的值。

此外,我认为通过使用临时H0_temp变量,我会避免让不同的线程有这种赛车状况问题。

!$OMP PARALLEL PRIVATE(i, H0_temp) 
    do i = inode1,inode2 
    H0_temp = H0(i) 
    if (mod(CEILING(Rat(1,i)*checkerDivider),2).ne.mod(CEILING(Rat(2,i)*checkerDivider),2)) then 
      H0_temp = H0_temp 
    else 
      H0_temp = H0_temp + onsiteShift 
    endif 
    H0(i) = H0_temp 
    end do 
    !$OMP END PARALLEL 

不过,它不起作用。我也尝试了一些沿线的减少...

基本上,如何使用OMP更改H0(i)的值? H0的最终结果应该是0或0.02。没有其他价值。如果我只使用一个处理器,则没有问题...

第二个问题,这个问题对我以前的计算有多大影响。我只注意到这个案例的问题,但我怀疑我的许多其他循环可能有同样的问题。或者当inode2的值非常大时(我的生产运行量约为2000万),它会以某种方式(希望)变得不那么成问题?

回答

2

你只是在

!$OMP PARALLEL DO PRIVATE(i) 

忘了DO因此没有工作共享发生,所有的线程正在做完整的循环。

关于附加问题:是的,这是一个严重的问题,你必须解决它。

+0

非常感谢。像大多数错误一样,一旦找到它们,它们就显得很愚蠢。我确实担心我必须再次完成大部分生产运行......顺便说一句,您提醒我发布最低工作代码是正确的,我在机场匆忙行事。无论如何,现在事情已经解决了。 – Nigu

+0

最后,似乎其他循环都可以。我建立在别人的代码上,他实际上使用了不同的方法来进行工作共享... inode1和inode2的值是THREADPRIVATE变量,对于每个线程都是不同的。但是对于这个具体的例子来说,事实并非如此。不是说我的问题或答案是重要的,而是为了完整性。 – Nigu