2013-08-18 93 views
3

當我使用Send/Recv時,我的代碼可以工作,但是當我用Isend/Irecv替換Send/Recv時,它會產生分段錯誤。但在去任何其他地方之前,我想驗證下面的代碼段是否看起來像是alrite。Isend/Irecv不起作用,但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 

但是,當我使用Isend/Irecv時,下面的行不會給出Segmentation故障。

CALL MPI_IRECV(CC(RSPANX(NT),RSPANY(NT),RSPANZ(NT)),SIZECC(NT),MPI_DOUBLE_PRECISION,NT,8,MPI_COMM_WORLD,REQ(NT+26),IERR) 
+1

不是一個答案,但我會建議使用調試器在這裏找到分段錯誤的來源。 – ricky116

回答

8

調用異步通信例程等MPI_ISENDMPI_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,它採用現代特徵在2008年Fortran和TS 29113與ASYNCHRONOUS屬性來標記,例如參數,並使陣列的安全通過具有不同尺寸(TYPE(*), DIMENSION(..)

+0

感謝您的回答。我會嘗試你所建議的。 – howitzer

相關問題