我的问题是,当我在Fortran中使用mpi方案时,我不知道如何调用子例程。我写了这个名为TRY.f90的小代码,其中有一个名为FOCUS.f90的子例程。我应该如何更改 FOCUS.f90 以使代码正常工作?
PROGRAM TRY
USE MPI
integer status(mpi_status_size)
INTEGER I, J, K, II, IERR, MY_ID, NUM_PROCS, PSP
INTEGER , PARAMETER :: GRIDX =64, GRIDY=64
REAL , DIMENSION(gridx,gridy) :: PSI
PSI=0
PRINT*, 'VARIABLE'
CALL MPI_INIT(IERR)
CALL MPI_COMM_RANK(MPI_COMM_WORLD,MY_ID,IERR)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD,NUM_PROCS,IERR)
CALL CONCENTRATION(GRIDX, GRIDY, NUM_PROCS, MY_ID , PSI)
IF (MY_ID .NE. 0) THEN
CALL mpi_send( PSI(1+MY_ID*GRIDX/NUM_PROCS:(MY_ID+1)*GRIDX/NUM_PROCS:1,1:GRIDY:1),&
(GRIDX/NUM_PROCS)*GRIDY,mpi_real, 0,10,mpi_comm_world,ierr)
END IF
IF (MY_ID .EQ. 0) THEN
DO II=1,NUM_PROCS-1
CALL mpi_recv(PSI(1+II*GRIDX/NUM_PROCS:(II+1)*GRIDX/NUM_PROCS:1,1:GRIDY:1),&
(GRIDX/NUM_PROCS)*GRIDY,mpi_real, &
II,10,mpi_comm_world,status,ierr)
END DO
END IF
CALL MPI_FINALIZE(IERR)
END PROGRAM TRY
我正在使用一个名为 FOCUS.f90 的子程序,它是:
SUBROUTINE CONCENTRATION(GRIDX, GRIDY, NUM_PROCS, MY_ID , PSI)
implicit none
INTEGER*8, INTENT(IN) :: GRIDX, GRIDY
INTEGER , INTENT(IN) :: NUM_PROCS, MY_ID
REAL*8 , DIMENSION(GRIDX,GRIDY), INTENT(OUT) :: PSI
INTEGER*8 I, J
DO I=1+MY_ID*GRIDX/NUM_PROCS, (MY_ID+1)*GRIDX/NUM_PROCS
DO J=1,GRIDY
PSI(I,J)=2.0
END DO
END DO
END SUBROUTINE CONCENTRATION
代码目前给了我错误,因为我认为我应该对子程序 FOCUS.f90 进行一些更改。或者我也应该改变我调用子例程的方式。
你能告诉我这些变化是什么吗?提前感谢您的帮助
由于类型不匹配,您的程序出现段错误。在主程序中,您已将PSI
声明为REAL
数组:
REAL , DIMENSION(gridx,gridy) :: PSI
而在CONCENTRATION
子例程中,您使用另一种类型的REAL*8
:
REAL*8 , DIMENSION(GRIDX,GRIDY), INTENT(OUT) :: PSI
默认情况下,REAL
长度为 4 个字节,而 REAL*8
(或 DOUBLE PRECISION
或 REAL(KIND=8)
)长度为 8 个字节。因此,您给CONCENTRATION
一个比它认为的数组小 2 倍的数组,并且从 NUM_PROCS/2
开始的所有等级都写入PSI
数组的末尾,从而导致段错误。如果仅使用一个进程运行,则即使排名 0 也会出现段错误。
您还应该阅读有关 MPI 集体操作的信息。 MPI_GATHER
和MPI_GATHERV
完全按照您在这里多次发送和接收来实现的目标。
唯一的更改是将concentration
声明为 reentrant
。 这可能是Fortran 90的默认值。 (我的大部分经验是 F77,reentrant
不是那里的默认。