回 帖 发 新 帖 刷新版面

主题:求救!数组在OpenMP并行后,数组数据出现NaN无效数据!

程序在做OpenMP并行后,并行区内的数据总会莫名其妙地出现NaN,然后结果就完全错误了。大家能帮我看一下是什么问题么? 下面是其中一段出现这样情况的程序,FX与FY属于并行区内被调用子函数hdifft_gm的局部变量,FX与FY这个变量的2次打印间没有被赋值过,但两次打印结果就不一样了,后一次打印的值间歇地出现了NaN无效数据。求大家帮我看一下问题出在哪里?这个问题折磨了我好久,没有办法解决!其他部分的并行代码也有类似的问题。对了,我用的是OpenMP与MPICH2的混合并行,在一个进程中再分出8个线程来执行代码。所以下面打印代表的是0号进程的1号线程的数据。
    if(my_task==0)then
         if(bid==1)then
              open(43,file='A3.txt')
              write(43,*)FX(i,j)
              open(44,file='A4.txt')
              write(44,*)FY(i,j)
          endif
    endif

            do j=this_block%jb,this_block%je
            do i=this_block%ib,this_block%ie

               fz = -KMASK(i,j)* &
                   (dz(k )*KPTMP1(i,j)* &
                    (SLX(i,j,ieast ,kbt ,bid)*HYX(i ,j,bid)* &
                                               TX(i ,j,kn,n,bid) &
                   + SLY(i,j,jnorth,kbt ,bid)*HXY(i ,j,bid)* &
                                               TY(i ,j,kn,n,bid) &
                   + SLX(i,j,iwest ,kbt ,bid)*HYX(i-1,j,bid)* &
                                               TX(i-1,j,kn,n,bid) &
                   + SLY(i,j,jsouth,kbt ,bid)*HXY(i,j-1,bid)* &
                                               TY(i,j-1,kn,n,bid)) &
                   + dz(k+1)*KPTMP2(i,j)* &
                    (SLX(i,j,ieast ,kbt2,bid)*HYX(i ,j,bid)* &
                                               TX(i ,j,ks,n,bid) &
                   + SLY(i,j,jnorth,kbt2,bid)*HXY(i ,j,bid)* &
                                               TY(i ,j,ks,n,bid) &
                   + SLX(i,j,iwest ,kbt2,bid)*HYX(i-1,j,bid)* &
                                               TX(i-1,j,ks,n,bid) &
                   + SLY(i,j,jsouth,kbt2,bid)*HXY(i,j-1,bid)* &
                                               TY(i,j-1,ks,n,bid)))
               GTK(i,j,n) = (FX(i,j) - FX(i-1,j) + FY(i,j) - FY(i,j-1) &
                          + FZTOP(i,j,n,bid) - fz)* &
                            dzr(k)*TAREA_R(i,j,bid)

               FZTOP(i,j,n,bid) = fz

               if(my_task==0)then
                   if(bid==1)then
                       open(37,file='H3.txt')
                       write(37,*)FX(i,j)
                       open(38,file='H4.txt')
                       write(38,*)FY(i,j)
                   endif
               endif

            end do
            end do



         else ! k=km
            do j=this_block%jb,this_block%je
            do i=this_block%ib,this_block%ie

               !fz = 0
               GTK(i,j,n) = (FX(i,j) - FX(i-1,j) + FY(i,j) - FY(i,j-1) &
                          + FZTOP(i,j,n,bid))* &
                            dzr(k)*TAREA_R(i,j,bid)

               FZTOP(i,j,n,bid) = c0

            end do
            end do
         endif

      endif

回复列表 (共7个回复)

沙发

我没看到你那里用了omp.
omp+mpi处理好关系应该没问题的, 虽然我只用过一次这样的混合.

板凳

哦,主要是!OMP那一段代码到我写出来那一段中间经过了2次的子函数调用,所以没写。

      !$OMP PARALLEL PRIVATE(iblock,k,kp1,km1,this_block,WTK)
   !$OMP DO
   do iblock = 1,nblocks_clinic
      this_block = get_block(blocks_clinic(iblock),iblock)

      do k = 1,km

         kp1 = k+1
         km1 = k-1

         ..........................

         call tracer_update(k, WTK, &
                               TRACER (:,:,:,:,newtime,iblock), &
                               TRACER (:,:,:,:,oldtime,iblock), &
                               TRACER (:,:,:,:,mixtime,iblock), &
                               TRACER (:,:,:,:,curtime,iblock), &
                               UVEL (:,:,: ,curtime,iblock), &
                               VVEL (:,:,: ,curtime,iblock), &
                               UVEL (:,:,: ,mixtime,iblock), &
                               VVEL (:,:,: ,mixtime,iblock), &
                               RHO (:,:,: ,curtime,iblock), &
                               STF (:,:,: ,iblock), &
                               TFW (:,:,: ,iblock), &
                               SHF_QSW(:,: ,iblock), &
                               DH (:,: ,iblock), &
                               PSURF (:,: ,oldtime,iblock), &
                               PSURF (:,: ,curtime,iblock), &
                               this_block,iblock)

    ........................................

   enddo ! first block loop

   !$OMP END DO
   !$OMP END PARALLEL

    一楼的代码可以看做tracer_update子函数的一部分

3 楼

就这样看代码,我看不出哪里有问题.
omp那里作为检查, 可以考虑使用default(none) 一个一个变量去确认它们的属性. 另一方面, NAN一般是有*/0的情况出现得到无穷大数,然后在演变成NAN, 追查一下它的来源应该找到突破点.

4 楼

default(none) 是在!$OMP里面定义么?‘一个一个变量去确认它们的属性’这个是怎么做?

5 楼

omp代码不是你写的吗? 不明白我的意思?

6 楼

不是很明白,可以举个例子么?

7 楼

除了子函数里面的临时变量(这些由线程开辟的天然就是私有), 一些parameter之外, 其他在并行区的变量都要赋予私有还是共有的属性. 不过一般编译器下变量默认是在共有属性的. 你的代码里面只声明了部分变量是private的变量. 比较保守的做法就是设置为default(none)然后一个一个变量去分类.

我来回复

您尚未登录,请登录后再回复。点此登录或注册