2013-10-27 58 views
0

我有一个基本问题。在下面的代码中,我调用了相同的函数'add',两次。当我使用OpenMP执行此操作时,我得到的结果不正确。在OpenMP fortran线程中调用函数

program p 
integer::i,j,omp_get_thread_num,n 
real::suma 
i=5 
j=10 

!$omp parallel num_threads(2) private(n) 

n=omp_get_thread_num() 

if(n==0) goto 1111 

suma=add(i,n) 

write(*,*)'sum for 5=',suma,n,i 

goto 1000 

1111 suma=add(j,n) 

write(*,*)'sum for 10=',suma,n,j 

1000 continue 

!$omp end parallel 

end program p 
!---------------------------------------- 

function add(k,n)result(l) 

implicit none 

integer::k,s,n 

real::l1,l 

!write(*,*)'thread employing me is:',n 

l1=0.0 

do s=k,k+5 

l1=l1+s 

end do 

l=l1 

return 

end function add 

执行这段代码的结果是:

sum for 10= 45.0000000    0   10 

sum for 5= 45.0000000    1   5 

然而,当我去掉22行,即 '写()!' 线程雇用我的是: 'N'

结果是:

thread employing me is:   0 

sum for 10= 75.0000000    0   10 

thread employing me is:   1 

sum for 5= 45.0000000    1   5 

我应该以采用相同的做函数使用不同的线程,正确(即没有混淆变量)任何人都可以解释获得的结果?

这是我的实际问题的简单版本。 (我在线程中使用相同的功能)

编辑:好的,我已经意识到在私人列表中不包含'suma'这个非常愚蠢的错误。但是,仍然有人可以说出为什么,如果第22行没有注释,它总是会给出正确的结果,即使suma不是私人的?

+0

我的猜测是,在'write'声明某种程度上是某种“隐性障碍“,st不同线程的不同写入语句是逐行给出的,而不是乱码。 –

+0

您应该在'private'子句的列表中添加'suma'。你应该真的使用OpenMP部分。 –

回答

4

程序中存在数据竞争条件。 sumashared(通过OpenMP的隐式数据共享规则),并且两个线程同时分配给它。取消注释write声明会导致第二个线程执行时出现轻微偏移,因此隐藏竞争条件(它不在我的OS X上 - 它只是使程序随机打印两次45.0或两次75.0)。

!$omp parallel num_threads(2) private(n, suma) 
... 
!$omp end parallel 

除此之外,你应该真的真的真的使用OpenMP的部分,而不是您所使用的goto逻辑:

!$omp parallel num_threads(2) private(n, suma) 
n=omp_get_thread_num() 

!$omp sections 
suma=add(i,n) 
write(*,*)'sum for 5=',suma,n,i 
!$omp section 
suma=add(j,n) 
write(*,*)'sum for 10=',suma,n,j 
!$omp end sections 

!$omp end parallel