【问题标题】:Why should I use MPI_REDUCE instead of MPI_ALLREDUCE?为什么我应该使用 MPI_REDUCE 而不是 MPI_ALLREDUCE?
【发布时间】:2023-02-01 04:29:46
【问题描述】:

我是非常MPI 编程的新手(两天前),这是我第一次发布有关堆栈溢出的问题。我现在正在处理MPI_ALLREDUCE和MPI_REDUCE。我知道两者之间的区别在于前者将减少变量的最终值传递给所有进程,而在后一种情况下仅传递给目标进程。在许多情况下甚至很难,您不需要将变量的更新值传递给子进程我不明白不这样做(或这样做)有什么好处。我最初虽然使用 MPI_REDUCE 可能会更好,这样就不会浪费计算时间来广播变量的值,但是我在我的代码中没有发现这两种情况有任何区别。我使用 2 到 6 之间的多个进程运行代码。

代码取值n,每个进程的任务是将变量mypartialsumn/num_procs加1次,其中num_procs为进程数。归约后mypartialsum的值聚集在sum中,最终结果为sum=n。

program test
      use mpi
      IMPLICIT NONE
      !include 'mpif.h'
      integer:: ierr, num_procs, my_id, status(MPI_STATUS_SIZE), sender(MPI_STATUS_SIZE), root, rank
      integer:: i, n
      !real:: sum=0., partialsum=0., mypartialsum=0.
      integer:: sum=0, partialsum=0, mypartialsum=0
      real:: starttime, endtime
      root=0

      call MPI_INIT ( ierr )
      call MPI_COMM_RANK (MPI_COMM_WORLD, my_id, ierr)
      call MPI_COMM_SIZE (MPI_COMM_WORLD, num_procs, ierr)
      starttime = MPI_WTIME()
      if (my_id .eq. root) then 
            print*, "Running in process 0."
            print*, "total numeber of process is", num_procs
            n=1d9!1000000000
      endif
      
      call MPI_BCAST(n, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
      !print*, "running process", my_id
      mypartialsum=0.
      do i = my_id+1, n, num_procs
            mypartialsum=mypartialsum+int(1)
     
      enddo 
      partialsum=mypartialsum
      print*, "Running process", my_id, "Partial sum is ", partialsum
      call MPI_REDUCE(partialsum, sum, 1, MPI_INTEGER, MPI_SUM, ROOT, MPI_COMM_WORLD, ierr)
      !call MPI_ALLREDUCE(partialsum, sum, 1, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD, ierr)

      endtime = MPI_WTIME()
      if (my_id .eq. 0) then
       print*, "sum is", sum, "time spent processing",  endtime-starttime
!      else if (my_id .gt. 0) then 
!       print*, "sum on process", my_id, "is", sum , "time spent processing is", endtime-starttime
      endif
     
     
      call MPI_FINALIZE ( ierr )
     

end program

【问题讨论】:

    标签: mpi


    【解决方案1】:

    第一:MPI 中没有“子”进程。在您的情况下,您任意指定一个进程作为集体的根,但 MPI 原则上是对称的:所有进程都是相同的。

    其次:您的观察是正确的:Allreduce 与 Reduce 的运行时间完全相同。

    那么为什么需要 Allreduce?因为这是实践中的常见情况。假设您有一个包含数十亿个元素的向量,这些元素分布在您的流程中。而且它太大而无法放在单个进程上,这就是为什么要使用分布式编程模型的原因。现在说你想规范化那个向量。这意味着 1. 通过某种归约计算范数, 2. 确保每个进程都知道该范数,以便 3. 每个进程都将自己的元素除以该范数。

    这种场景在科学应用中很常见,这就是为什么我认为MPI_Allreduce是最基本的集体例程。

    【讨论】:

      猜你喜欢
      • 2016-05-23
      • 2018-05-10
      • 2014-03-12
      • 2012-12-13
      • 2013-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多