Fortran 在子程序中使用MPI
我正在编写多次串行调用子例程(子例程反过来执行迭代)的代码。我希望在子例程中并行化迭代。mpi的问题是我只能初始化它一次。因此,我无法在我的子例程中初始化它,它会被多次调用。有人能提出一个解决办法吗 我的问题大致如下:Fortran 在子程序中使用MPI,fortran,mpi,subroutine,Fortran,Mpi,Subroutine,我正在编写多次串行调用子例程(子例程反过来执行迭代)的代码。我希望在子例程中并行化迭代。mpi的问题是我只能初始化它一次。因此,我无法在我的子例程中初始化它,它会被多次调用。有人能提出一个解决办法吗 我的问题大致如下: program p ... do i=1,10000 call subroutine s(i) end do end program p subroutine s(j) ... do i=1,10000 ... end do end subrou
program p
...
do i=1,10000
call subroutine s(i)
end do
end program p
subroutine s(j)
...
do i=1,10000
...
end do
end subroutine s
我希望将这个过程并行化
非常感谢。那有帮助!但让我重新审视我的问题,
在主程序的迭代中,连同子例程s,我必须调用另一个子例程s2(不需要并行化)。我想,可以这样做:
!initialize mpi
do i=1:1000
if rank!=0
call s
else call s2
end if
end do
!finalize mpi
但这里的主要问题是,虽然其余进程进展缓慢,但进程0将快速进行。(不可取的东西)。那么,是否可以让进程0在每次迭代后等待,直到另一个进程完成其迭代 您需要在主程序中初始化并完成MPI。通常,然后在子例程中定义对工作有效的负载平衡 然后并行地在子例程内部执行循环,并在子例程末尾收集(减少?)结果,以便在下次调用子例程时获得所需的所有信息 这与主程序中的循环(不调用子例程)的工作方式相同 下面是一个最起码的例子:
module testMod
use mpi
implicit none
!#include "mpif.h"
!===
contains
!===
subroutine s(mysize, myrank, array)
integer,intent(in) :: mysize, myrank
integer,intent(inout) :: array(:)
integer :: i, ierror
! Do stuff
do i=1,size(array)
! Skip element that is not associated with the current process
if ( mod(i,mysize) .ne. myrank ) cycle
array(i) = array(i) + 1
enddo ! i
! MPI Allreduce
call MPI_Allreduce(MPI_IN_PLACE, array, size(array), MPI_INTEGER, &
MPI_MAX, MPI_COMM_WORLD, ierror)
end subroutine
end module
program mpiTest
use testMod
use mpi
implicit none
!#include "mpif.h"
integer :: mysize, myrank, ierror
integer,parameter :: ITER=100
integer,parameter :: arraySize=10
integer :: work(arraySize)
integer :: i
! MPI Initialization
call MPI_Init(ierror)
call MPI_Comm_rank(MPI_COMM_WORLD, myrank, ierror)
call MPI_Comm_size(MPI_COMM_WORLD, mysize, ierror)
work = 0
do i=1,ITER
call s(mysize, myrank, work)
enddo
if ( myrank .eq. 0 ) write(*,*) work
! MPI Finalize
call MPI_Finalize(ierror)
end program
您需要在主程序中初始化并完成MPI。通常,然后在子例程中定义对工作有效的负载平衡 然后并行地在子例程内部执行循环,并在子例程末尾收集(减少?)结果,以便在下次调用子例程时获得所需的所有信息 这与主程序中的循环(不调用子例程)的工作方式相同 下面是一个最起码的例子:
module testMod
use mpi
implicit none
!#include "mpif.h"
!===
contains
!===
subroutine s(mysize, myrank, array)
integer,intent(in) :: mysize, myrank
integer,intent(inout) :: array(:)
integer :: i, ierror
! Do stuff
do i=1,size(array)
! Skip element that is not associated with the current process
if ( mod(i,mysize) .ne. myrank ) cycle
array(i) = array(i) + 1
enddo ! i
! MPI Allreduce
call MPI_Allreduce(MPI_IN_PLACE, array, size(array), MPI_INTEGER, &
MPI_MAX, MPI_COMM_WORLD, ierror)
end subroutine
end module
program mpiTest
use testMod
use mpi
implicit none
!#include "mpif.h"
integer :: mysize, myrank, ierror
integer,parameter :: ITER=100
integer,parameter :: arraySize=10
integer :: work(arraySize)
integer :: i
! MPI Initialization
call MPI_Init(ierror)
call MPI_Comm_rank(MPI_COMM_WORLD, myrank, ierror)
call MPI_Comm_size(MPI_COMM_WORLD, mysize, ierror)
work = 0
do i=1,ITER
call s(mysize, myrank, work)
enddo
if ( myrank .eq. 0 ) write(*,*) work
! MPI Finalize
call MPI_Finalize(ierror)
end program
请以正确的标记格式输入代码,以提高可读性您调用将屏障插入主循环:
调用MPI\u屏障(MPI\u COMM\u WORLD,ierror)
。所有进程都必须等到最后一个进程到达屏障。但你为什么要这么做?如果一个进程明显比其他进程慢,那么负载平衡可能有问题!我基本上是在10000个时间步上运行模拟。对于每个时间步,子程序S必须运行1000个步骤的迭代,得到一个值,然后由子程序S2使用,这是一个不太麻烦的子程序,(不需要并行化),然后我们进入下一个时间步(10000个时间步中)。我只能连续地移动时间(因为每次迭代中使用的常量取决于前面的时间步)。S基本上为同一时间步长的许多粒子解同一组方程。如果S
和s2
是完全不同的例程,调用s2
而不是S
将产生错误的结果,因为过程0
将不参与计算!因此,我建议使用调用s;如果(秩==0)调用s2
。如果s2
要短得多,并且下一次迭代需要它的结果,我建议在每个进程上调用s2
(无需进一步通信!)。请将代码放入正确的标记格式以提高可读性您调用在主循环中插入一个屏障:调用MPI_屏障(MPI_COMM_WORLD,ierror)
。所有进程都必须等到最后一个进程到达屏障。但你为什么要这么做?如果一个进程明显比其他进程慢,那么负载平衡可能有问题!我基本上是在10000个时间步上运行模拟。对于每个时间步,子程序S必须运行1000个步骤的迭代,得到一个值,然后由子程序S2使用,这是一个不太麻烦的子程序,(不需要并行化),然后我们进入下一个时间步(10000个时间步中)。我只能连续地移动时间(因为每次迭代中使用的常量取决于前面的时间步)。S基本上为同一时间步长的许多粒子解同一组方程。如果S
和s2
是完全不同的例程,调用s2
而不是S
将产生错误的结果,因为过程0
将不参与计算!因此,我建议使用调用s;如果(秩==0)调用s2
。如果s2
要短得多,并且下一次迭代需要它的结果,我建议在每个进程上调用s2
(无需进一步沟通!)。非常感谢您的回答。非常感谢您的回答。