fortran openmp嵌套循环通信开销

时间:2013-04-24 16:09:01

标签: fortran openmp

我的目标是远离MATLAB,并在Fortran中完成大部分工作。其中一项努力是通过MATLAB的parfor循环用Fortran openMP指令代替并行化。这总是更快,但由于某种原因,使用openMP的CPU利用率(由taskmgr测量)低于parfor(特别是对于较小的问题)。我的假设是,这是由于通信开销,如果CPU利用率接近100%(如MATLAB),那么对于小问题,代码会快得多。我的问题有两方面:

  1. 有没有办法提高以下代码的效率(使用openMP指令)?
  2. 如果没有,效率低下的原因是什么?你建议如何补救它?
  3. 尝试(不成功)决议:

    1. 添加子句折叠(5)(对于5个嵌套循环)
    2. 明确声明所有内容(即不使用默认(共享))
    3. KMP_SET_BLOCKTIME(1000)保持线程打开,直到下一个omp并行执行
    4. CPU利用率数据(Windows 7 64位,双核四核intel xeon 3Ghz):

      • 小问题(* _pts = 5):
        Fortran(openMP),时间:40s,CPU使用率:60%
        MATLAB(parfor),时间:45s,CPU使用率:90%
        - > MATLAB需要1.125倍

      • 中等问题(* _pts = 6):
        Fortran(openMP),时间:78s,CPU使用率:75%
        MATLAB(parfor),时间:96s,CPU使用率:90%
        - > MATLAB需要1.231倍

      • 大问题(* _pts = 7):
        Fortran(openMP),时间:150s,CPU使用率:100%
        MATLAB(parfor),时间:205s,CPU使用率:100%
        - > MATLAB需要1.367倍

      示例:

          do while (converged == -1)
          istart = omp_get_wtime()               ! Iteration timer start
          !$omp parallel do default(shared) private(start,state,argzero)
          do i5 = 1,Oepsr_pts
           do i4 = 1,Ozeta_pts
            do i3 = 1,Oz_pts
             do i2 = 1,Or_pts
              do i1 = 1,Opd_pts
               start(1,1) = pfn(i1,i2,i3,i4,i5)
               start(2,1) = pfx1(i1,i2,i3,i4,i5)
               start(3,1) = pfx2(i1,i2,i3,i4,i5)
               state = [Gpd_grid(i1),Gr_grid(i2),Gz_grid(i3),Gzeta_grid(i4),Gepsr_grid(i5)];
               ! Find optimal policy functions on each node
               argzero = 0.d0
               call csolve(start,nstate,npf,nshock,Opd_pts,Or_pts,Oz_pts,Ozeta_pts,Oepsr_pts,Omono_pts,state, &
                              Smu,Schi,Sr,Sy,Pomega,Ptheta,Psigma,Peta,Pzbar, &
                              Prhor,Ppi,Pphipi,Pphiy,Prhoz,Pzetabar,Prhozeta,Pbeta, &
                              Gpd_grid,Gr_grid,Gz_grid,Gzeta_grid,Gepsr_grid,Gmono_nodes,Gmono_weight, &
                              pfn,pfx1,pfx2,argzero)
               ! Store updated policy functions
               pfn_up(i1,i2,i3,i4,i5) = argzero(1,1)
               pfx1_up(i1,i2,i3,i4,i5) = argzero(2,1)
               pfx2_up(i1,i2,i3,i4,i5) = argzero(3,1)
              end do
             end do
            end do
           end do
          end do
          !$omp end parallel do
      
          ! Policy function distances    
          dist_n = abs(pfn_up - pfn);  
          dist_x1 = abs(pfx1_up - pfx1);
          dist_x2 = abs(pfx2_up - pfx2);
      
          ! Maximum distance
          dist_max(it) = max(maxval(dist_n),maxval(dist_x1),maxval(dist_x2));
      
          ! Update policy functions
          pfn = pfn_up;
          pfx1 = pfx1_up;
          pfx2 = pfx2_up;
      
          ! Check convergence criterion
          if ((it > 11) .AND. all(dist_max(it-10:it) < Ptol)) then 
              converged = 1;
          else if (dist_max(it) > 10 .OR. it > 2500) then
              converged = 0;
          end if
      
          ! Iteration Information
          iend = omp_get_wtime()
          if (mod(it,3) == 1 .OR. converged == 1 .OR. converged == 0) then
              call itinfo(tstart,istart,iend,it,dist_max(it));
          else
              it = it + 1
          end if
      end do
      

1 个答案:

答案 0 :(得分:0)

添加崩溃条款消除了低效率。     !$ omp崩溃(5) 否则,正如Jermiah Willcock指出的那样,只有外环可以并行运行。我相信我是在6核的计算机上进行测试,外环恰好有6个点,所以当时效率没有下降。只有当我切换到具有更多内核的计算机时才会出现问题。很高兴知道!

谢谢M.S.B.和耶利米,你的快速和有益的回应。一切都好了!