Multithreading 具有1个或n个线程的OPENMP再现性

Multithreading 具有1个或n个线程的OPENMP再现性,multithreading,openmp,locks,Multithreading,Openmp,Locks,我正致力于并行化代码的一小部分,其中包含do循环和调用子例程。但1个线程或2个线程的结果不一致 对于这种类型的程序,我们必须使用锁吗 !$OMP parallel private(kk,j,i,k1,j1,i1,k2,j2,i2,ic,icm,xx,yy,ydatm),shared(undef,lt,ln,nd,xd,tgrd,ndaym) thread_id = OMP_GET_THREAD_NUM() num_threads = OMP_GET_NUM_THREADS() if(t

我正致力于并行化代码的一小部分,其中包含do循环和调用子例程。但1个线程或2个线程的结果不一致

对于这种类型的程序,我们必须使用锁吗

!$OMP parallel private(kk,j,i,k1,j1,i1,k2,j2,i2,ic,icm,xx,yy,ydatm),shared(undef,lt,ln,nd,xd,tgrd,ndaym)
 thread_id   = OMP_GET_THREAD_NUM()
 num_threads = OMP_GET_NUM_THREADS()
 if(thread_id.eq.0) thread_id=thread_id+1
 start_no    = (thread_id * ndaym / num_threads);
 end_no      = ((thread_id + 1) * ndaym / num_threads);
 xx(:)=undef
 yy(:,:)=undef 

!$OMP DO 
 DO kk=start_no,end_no

  do j=1,nlat
   do i=1,nlon
    ic=0
    do k1=kk-nd,kk+nd
     k2=k1
     if(k2.lt.1)k2=1
     if(k2.gt.ndaym)k2=ndaym
     do j1=j-lt,j+lt
      j2=j1
      if(j2.lt.1)j2=1
      if(j2.gt.nlat)j2=nlat
      do i1=i-ln,i+ln
       i2=i1
       if(i2.lt.1)i2=1
       if(i2.gt.nlon)i2=i2-nlon
       ic=ic+1
       yy(ic,:)=xdatm(i2,j2,k2,:)
       yya(:) = yy(ic,:)
       call funcmean(yya,xx(ic),1,nmem,nmem,undef)
       if(k1.eq.kk.and.j1.eq.j.and.i1.eq.i) then
         icm=ic
         call funcsd(yya,1,nmem,nmem,undef,xx(ic),xd)
       endif
      enddo  ! for i1       
     enddo   ! for j1
    enddo   ! for k1
   call funcens(xx,yy,tgrd,nmem,icm,undef,dist)
    ydatm(i,j,kk,:)= dist(:)
  enddo !for nlon
 enddo ! for nlat   
 ENDDO !kk

!$OMP end do
deallocate(xx,yy)
!$OMP end parallel

有人能提供一些线索吗?

我不确定代码的其余部分是否正确(实际上我甚至没有试着阅读TBH),但开头显然是错的:

!$OMP parallel private(kk,j,i,k1,j1,i1,k2,j2,i2,ic,icm,xx,yy,ydatm),shared(undef,lt,ln,nd,xd,tgrd,ndaym)
 thread_id   = OMP_GET_THREAD_NUM()
 num_threads = OMP_GET_NUM_THREADS()
 if(thread_id.eq.0) thread_id=thread_id+1
 start_no    = (thread_id * ndaym / num_threads);
 end_no      = ((thread_id + 1) * ndaym / num_threads);
我将尝试总结我在这段代码中发现的错误:

  • 变量
    thread\u id
    num\u threads
    start\u no
    end\u no
    未声明为
    private
    。因此,它们被隐式地
    共享
    ,这显然是非常错误的。为了避免这种基本陷阱,我强烈建议您在
    中使用
    default(none)
    子句$omp并行指令。这肯定会让你省去很多麻烦
  • 如果(thread\u id.eq.0)thread\u id=thread\u id+1
    :那么假设
    thread\u id
    已经声明为私有的
    。之后,两个不同的线程(线程0和线程1)的
    thread\u id
    的值都相同,即1。这有什么意义
  • 然后,使用线程0的伪值
    线程id
    计算
    start\u no
    end\u no
    (即使声明了
    private
首先尝试修复这些,看看它能带来什么


额外看一眼代码的其余部分,我怀疑
deallocate(xx,yy)
也可能是一个问题:除非分配是在并行区域完成的(这里看起来不是这样,但仍然是可能的),解除分配应该移到它之外。

我不确定代码的其余部分是否正确(实际上我甚至没有尝试阅读TBH),但开头显然是错误的:

!$OMP parallel private(kk,j,i,k1,j1,i1,k2,j2,i2,ic,icm,xx,yy,ydatm),shared(undef,lt,ln,nd,xd,tgrd,ndaym)
 thread_id   = OMP_GET_THREAD_NUM()
 num_threads = OMP_GET_NUM_THREADS()
 if(thread_id.eq.0) thread_id=thread_id+1
 start_no    = (thread_id * ndaym / num_threads);
 end_no      = ((thread_id + 1) * ndaym / num_threads);
我将尝试总结我在这段代码中发现的错误:

  • 变量
    thread\u id
    num\u threads
    start\u no
    end\u no
    未声明为
    private
    。因此,它们被隐式地
    共享
    ,这显然是非常错误的。为了避免这种基本陷阱,我强烈建议您在
    中使用
    default(none)
    子句$omp并行指令。这肯定会让你省去很多麻烦
  • 如果(thread\u id.eq.0)thread\u id=thread\u id+1
    :那么假设
    thread\u id
    已经声明为私有的
    。之后,两个不同的线程(线程0和线程1)的
    thread\u id
    的值都相同,即1。这有什么意义
  • 然后,使用线程0的伪值
    线程id
    计算
    start\u no
    end\u no
    (即使声明了
    private
首先尝试修复这些,看看它能带来什么


额外看一眼代码的其余部分,我怀疑
deallocate(xx,yy)
也可能是一个问题:除非分配是在并行区域完成的(这里看起来不是这样,但仍然是可能的),解除分配应该移到它的外部。

在我看来,好像您正在试图计算每个线程在外部do循环迭代中所占的份额,而所有这些都是为了计算
start\u no
end\u no
。如果是这样的话,您就错过了OpenMP的一个要点,那就是编译器会为您做这件事。网络上有很多很好的例子,甚至在这里,向您展示了Fortran+OpenMP中并行do循环的一般超级结构。在我看来,您似乎在试图计算每个线程在外部do循环迭代中所占的份额,而所有这些都是为了计算
start\u no
end\u no
。如果是这样的话,您就错过了OpenMP的一个要点,那就是编译器会为您做这件事。网络上有很多很好的例子,即使在这里,也可以向您展示Fortran+OpenMP中并行do循环的一般超级结构。@HighPerformanceMark很公平,我在这里没有考虑自动分配。但正如您所指出的,语法似乎是伪造的。@HighPerformanceMark经过再三考虑,即使假设自动分配语法正确,
unde
xx
似乎是1D而
yy
似乎是2D的情况下,如何用于此目的?这两项作业中至少有一项不起作用,是吗?@HighPerformanceMark很公平,我没有想到这里会自动分配。但正如您所指出的,语法似乎是伪造的。@HighPerformanceMark经过再三考虑,即使假设自动分配语法正确,
unde
xx
似乎是1D而
yy
似乎是2D的情况下,如何用于此目的?这两项作业中至少有一项不起作用,是吗?