Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 在子程序中使用MPI_Fortran_Mpi_Subroutine - Fatal编程技术网

Fortran 在子程序中使用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

我正在编写多次串行调用子例程(子例程反过来执行迭代)的代码。我希望在子例程中并行化迭代。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 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
(无需进一步沟通!)。非常感谢您的回答。非常感谢您的回答。