Isend/Irecv不起作用,但Send/Recv确实如此

how*_*zer 3 fortran mpi fortran90

当我使用Send/Recv时,我的代码可以工作但是当我用Isend/Irecv替换Send/Recv时会产生分段错误.但在去其他任何地方之前,我想验证以下代码段是否显示为alrite.

其余的代码应该没问题,因为Send/Recv可以工作; 但是我没有把它粘贴在这里作为它的长代码.

    INTEGER :: IERR,TASKID,NUMTASKS,SPANX,SPANY,SPANZ,PROCSX,PROCSY,PROCSZ,STAT,STATUS(MPI_STATUS_SIZE),ISTAT(MPI_STATUS_SIZE,52)
    INTEGER,DIMENSION(1:52) :: REQ

 ALLOCATE(RCC(IIST:IIEND,JJST:JJEND,KKST:KKEND),STAT=IERR)  
 IF (IERR /=0) PRINT*,'ERROR IN RCC BY',TASKID

 DO I=1,52
 REQ(I)=MPI_REQUEST_NULL  
 ENDDO

 IF (TASKID.NE.0) THEN   
 NT=TASKID
 CALL MPI_ISEND(RCC(IIST:IIEND,JJST:JJEND,KKST:KKEND),SIZE(RCC),MPI_DOUBLE_PRECISION,0,8,MPI_COMM_WORLD,REQ(NT),IERR)
 ENDIF

 IF (TASKID.EQ.0) THEN     
 DO NT = 1,26
 CALL MPI_IRECV(CC(RSPANX(NT):RSPANXE(NT),RSPANY(NT):RSPANYE(NT),RSPANZ(NT):RSPANZE(NT)),SIZECC(NT),MPI_DOUBLE_PRECISION,NT,8,MPI_COMM_WORLD,REQ(NT+26),IERR)   
 ENDDO       
 ENDIF  

 CALL MPI_WAITALL(52,REQ,ISTAT,IERR)

  DEALLOCATE(RCC,STAT=IERR) 
  IF (IERR /=0) PRINT*,'ERROR IN DEALLOCATE RCC BY',TASKID 

  CALL MPI_FINALIZE(IERR)
  RETURN
  END
Run Code Online (Sandbox Code Playgroud)

但是,当我使用Isend/Irecv时,以下行不会给出分段错误.

  CALL MPI_IRECV(CC(RSPANX(NT),RSPANY(NT),RSPANZ(NT)),SIZECC(NT),MPI_DOUBLE_PRECISION,NT,8,MPI_COMM_WORLD,REQ(NT+26),IERR)  
Run Code Online (Sandbox Code Playgroud)

Hri*_*iev 8

调用异步通信程序一样MPI_ISEND,并MPI_IRECV与阵列的部分,例如RCC(IIST:IIEND,JJST:JJEND,KKST:KKEND),是非常危险的.原因是由于旧Fortran标准的限制,大多数MPI实现不为这些例程提供适当的接口,并且编译器将数据从数组部分复制到临时连续存储中,然后将其传递给子例程.由于临时存储在实际数据传输发生之前MPI_ISEND/ MPI_IRECV之前被释放,因此可能发生分段故障.您可以通过手动分配连续数组并在那里复制数据来防止这种情况发生.

另一方面,CC(RSPANX(NT),RSPANY(NT),RSPANZ(NT))不是指数组的一部分,而是指单个元素的位置.在这种情况下,不会创建数据的临时副本.

MPI-3.0提供了一组改进的Fortran绑定mpi_f08,它使用Fortran 2008和TS 29113中的现代功能来使用ASYNCHRONOUS属性标记这些参数,并启用具有不同维度的数组的安全传递(TYPE(*), DIMENSION(..))