You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MPI_Gather子矩阵聚合问题:多处理器运行时程序挂起

问题分析与修复方案

你的代码在多进程环境下挂起的核心原因是MPI集体操作要求通信域内所有进程同步调用,而代码中多处仅让根进程(rank=0)执行MPI_Gather,其他进程未参与这些操作,导致进程间无法同步,最终引发挂起。

具体问题点

1. 主程序iDebug分支的MPI_Gather调用错误

你将MPI_Gather放在if (my_rank == 0)块内,只有根进程执行该调用,其他进程未参与。而MPI_Gather是集体通信接口,必须所有进程同时调用,否则会一直等待未执行的进程,导致挂起。

2. print_whole_matr子程序的调用条件错误

主程序中调用该子程序的条件是if ((iN <= 30) .and. (my_rank == 0)),仅根进程进入子程序,其他进程无此操作。但子程序内部的MPI_Gather是集体操作,缺少其他进程参与时,根进程会一直等待,引发挂起。

修复后的完整代码

主程序修复版本

program matrix_manip

IMPLICIT NONE

include 'mpif.h'

integer   my_rank,num_proc  !! local rank of processor, total number of processors
integer   iM,iN,local_n     !! rows x columns, default 3x8 ... then n --> local_n = n/p
integer   status(MPI_STATUS_SIZE)
integer   ierr,iDebug
integer   local_i,local_j,j_my_rank,j,i     !! dumb loop indices

double precision  startTime, endTime, tsec
double precision, allocatable:: local_x(:),local_matr(:,:), print_matr(:,:)

call docommandline(iM,iN)

call MPI_INIT(ierr)

call MPI_Barrier(MPI_COMM_WORLD,ierr)
startTime = MPI_Wtime(ierr)

call MPI_COMM_RANK(MPI_COMM_WORLD, my_rank,  ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, num_proc, ierr)

local_n = iN/num_proc
if (abs(local_n*num_proc - iN) .NE. 0) then
  print *,'LARGE MATRIX : iM = ',iM,' iN = ',iN,' num_proc = ',num_proc
  print *,'cannot do integer iN/num_proc, quitting'
  call MPI_FINALIZE(ierr)
  stop
else
  write(*,'(5(A,I4))') ' LARGE MATRIX : ',iM,' x ',iN,' num_proc = ',num_proc,' local_n = ',local_n,' myrank = ',my_rank
end if

!! do this on every processor
allocate(local_x(iN))
allocate(local_matr(iM,local_n))
do local_j = 1,local_n
  do local_i = 1,iM
    j_my_rank = local_n * my_rank + local_j
    local_matr(local_i,local_j) = 10*local_i + j_my_rank
!    print *,my_rank,local_matr(local_i,local_j)
  end do
end do
print *,'here after init local_matr',my_rank

!! do this on all processors, only root handles allocation/printing
iDebug = +1
if (iDebug > 0) then
  call MPI_Barrier(MPI_COMM_WORLD,ierr)
  if (my_rank == 0) then
    allocate(print_matr(iM,iN))
    print *,'in main routine, called MPI_Barrier, allocated space for print_matr ... now gonna do GATHER'
  end if
  ! 所有进程同步调用MPI_Gather
  call MPI_GATHER(local_matr,iM*local_n,MPI_DOUBLE_PRECISION, &  !! everyone sends iM*local_n to root
                  print_matr,iM*local_n,MPI_DOUBLE_PRECISION, &  !! root gets iM*local_n from everyone *orders it correctly*
                  0,MPI_COMM_WORLD,ierr)
  if (my_rank == 0) then
    do j=1,iN
      write(*,'(A,I3,A,I3)') 'column ',j,' of ',iN
      do i=1,iM
        write(*,'(F24.16)') print_matr(i,j)
      end do
    end do
    deallocate(print_matr)
    print *,'finished printing matrix at main'
  end if
end if

!! 所有进程都调用print_whole_matr,仅根进程处理打印逻辑
if (iN <= 30) then
  call print_whole_matr(iM,iN,local_n,local_matr,num_proc,my_rank)
end if

call MPI_Barrier(MPI_COMM_WORLD,ierr)
endTime = MPI_Wtime(ierr);
if (my_rank .EQ. 0) THEN
  tsec = endTime - startTime
  write(*,'(A,I4,A,F10.6)') 'numprocessor = ',num_proc, '     wall clock time (s) ',tsec
end if

deallocate(local_x)
deallocate(local_matr)
call MPI_FINALIZE(ierr)
end

子程序修复版本

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine print_whole_matr(iM,iN,local_n,local_matr,num_proc,my_rank)

IMPLICIT NONE

include 'mpif.h'

! input variables
integer iM,iN,local_n
integer num_proc,my_rank
double precision :: local_matr(iM,local_n)

! local variables
double precision, allocatable :: print_matr(:,:)
integer i,j,ierr

if (my_rank == 0) then
  allocate(print_matr(iM,iN))
end if

call MPI_Barrier(MPI_COMM_WORLD,ierr)
! 所有进程同步调用MPI_Gather
call MPI_GATHER(local_matr,iM*local_n,MPI_DOUBLE_PRECISION, &  !! everyone sends iM*local_n to root
                print_matr,iM*local_n,MPI_DOUBLE_PRECISION, &  !! root gets iM*local_n from everyone *orders it correctly*
                0,MPI_COMM_WORLD,ierr)

if (my_rank == 0) then
  do i = 1,iM
    do j = 1,iN
      if (j .lt. iN) then
        write(*,'(F12.6,1X)',advance='no') print_matr(i,j)
      else
        write(*,'(F12.6,1X)') print_matr(i,j)
      end if
    end do
  end do
end if

if (my_rank == 0) then
  deallocate(print_matr)
end if

return
end

关键注意事项

  • MPI集体通信规则:MPI_Gather、MPI_Barrier这类集体操作,必须保证通信域内所有进程都调用,否则会触发进程挂起等待。
  • 数据聚合逻辑:你的按列拆分矩阵的逻辑是正确的,MPI_Gather会按进程rank顺序自动将子矩阵拼接为完整矩阵,符合预期。

内容的提问来源于stack exchange,提问作者SergioSM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 12:55:55