From b246f66e2cb843f2630b55dba64ae2604ea6eafa Mon Sep 17 00:00:00 2001 From: ESCOBAR Juan <escj@nuwa> Date: Mon, 9 Nov 2020 14:34:06 +0100 Subject: [PATCH] Juan 09/11/2020:get_halo.f90, version with GPU_DIRECT --- src/MNH/get_halo.f90 | 765 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 632 insertions(+), 133 deletions(-) diff --git a/src/MNH/get_halo.f90 b/src/MNH/get_halo.f90 index f3a9670ec..8b2522eef 100644 --- a/src/MNH/get_halo.f90 +++ b/src/MNH/get_halo.f90 @@ -16,6 +16,9 @@ INTERFACE SUBROUTINE GET_HALO2(PSRC, TP_PSRC_HALO2_ll, HNAME) ! USE MODD_ARGSLIST_ll, ONLY : HALO2LIST_ll + ! + IMPLICIT NONE + ! REAL, DIMENSION(:,:,:), INTENT(IN) :: PSRC ! variable at t TYPE(HALO2LIST_ll), POINTER :: TP_PSRC_HALO2_ll ! halo2 for SRC character(len=*), optional, intent(in) :: HNAME ! Name of the field to be added @@ -25,6 +28,7 @@ END INTERFACE ! INTERFACE SUBROUTINE GET_HALO(PSRC, HDIR, HNAME) + IMPLICIT NONE ! REAL, DIMENSION(:,:,:), INTENT(IN) :: PSRC ! variable at t CHARACTER(len=4), OPTIONAL :: HDIR ! to send only halo on X or Y direction @@ -36,6 +40,7 @@ END INTERFACE #ifdef MNH_OPENACC INTERFACE SUBROUTINE GET_HALO_D(PSRC, HDIR, HNAME) + IMPLICIT NONE ! REAL, DIMENSION(:,:,:), INTENT(INOUT) :: PSRC ! variable at t CHARACTER(len=4), OPTIONAL :: HDIR ! to send only halo on X or Y direction @@ -43,16 +48,40 @@ INTERFACE ! END SUBROUTINE GET_HALO_D END INTERFACE -#endif ! INTERFACE -SUBROUTINE DEL_HALO2_ll(TPHALO2LIST) -! -USE MODD_ARGSLIST_ll, ONLY : HALO2LIST_ll -TYPE(HALO2LIST_ll), POINTER :: TPHALO2LIST ! list of HALO2_lls -! -END SUBROUTINE DEL_HALO2_ll + SUBROUTINE GET_HALO_START_D(PSRC,KNB_REQ,KREQ,HDIR) + IMPLICIT NONE + ! + REAL, DIMENSION(:,:,:), INTENT(INOUT) :: PSRC ! variable at t + !$acc declare present (PSRC) + INTEGER :: KNB_REQ , KREQ(8) + CHARACTER(len=4), OPTIONAL :: HDIR ! to send only halo on X or Y direction + ! + END SUBROUTINE GET_HALO_START_D +END INTERFACE +INTERFACE + SUBROUTINE GET_HALO_STOP_D(PSRC,KNB_REQ,KREQ,HDIR) + IMPLICIT NONE + REAL, DIMENSION(:,:,:), INTENT(INOUT) :: PSRC ! variable at t + !$acc declare present (PSRC) + INTEGER :: KNB_REQ , KREQ(8) + CHARACTER(len=4), OPTIONAL :: HDIR ! to send only halo on X or Y direction + END SUBROUTINE GET_HALO_STOP_D +END INTERFACE +#endif ! +INTERFACE + SUBROUTINE DEL_HALO2_ll(TPHALO2LIST) + ! + USE MODD_ARGSLIST_ll, ONLY : HALO2LIST_ll + ! + IMPLICIT NONE + ! + TYPE(HALO2LIST_ll), POINTER :: TPHALO2LIST ! list of HALO2_lls + ! + END SUBROUTINE DEL_HALO2_ll + ! END INTERFACE ! END MODULE MODI_GET_HALO @@ -132,16 +161,412 @@ END SUBROUTINE GET_HALO !----------------------------------------------------------------------- #ifdef MNH_OPENACC MODULE MODD_HALO_D -IMPLICIT NONE -REAL, SAVE , ALLOCATABLE, DIMENSION(:,:,:) :: ZNORTH_IN, ZSOUTH_IN, ZWEST_IN, ZEAST_IN -REAL, SAVE , ALLOCATABLE, DIMENSION(:,:,:) :: ZNORTH_OUT, ZSOUTH_OUT, ZWEST_OUT, ZEAST_OUT + + IMPLICIT NONE + + REAL, SAVE , ALLOCATABLE, DIMENSION(:,:,:) :: ZNORTH_IN, ZSOUTH_IN, ZWEST_IN, ZEAST_IN + REAL, SAVE , ALLOCATABLE, DIMENSION(:,:,:) :: ZNORTH_OUT, ZSOUTH_OUT, ZWEST_OUT, ZEAST_OUT + + LOGICAL, SAVE :: GFIRST_GET_HALO_D = .TRUE. + + LOGICAL, SAVE :: GFIRST_INIT_HALO_D = .TRUE. + INTEGER, SAVE :: IHALO_1 + INTEGER, SAVE :: NP_NORTH,NP_SOUTH,NP_WEST,NP_EAST + +CONTAINS + + SUBROUTINE INIT_HALO_D() + + USE MODE_MNH_ZWORK, ONLY : IIU,IJU,IKU + USE MODE_MNH_ZWORK, ONLY : IIB,IJB ,IIE,IJE + USE MODE_MNH_ZWORK, ONLY : GWEST , GEAST, GSOUTH , GNORTH + USE MODD_CONF, ONLY : NHALO -LOGICAL, SAVE :: GFIRST_GET_HALO_D = .TRUE. + USE MODD_VAR_ll, ONLY : IP,NPROC,NP1,NP2 + + + IMPLICIT NONE + + IF (GFIRST_INIT_HALO_D) THEN + ! + IHALO_1 = NHALO-1 + ! + ALLOCATE ( ZSOUTH_IN ( IIB:IIE , IJB:IJB+IHALO_1 , IKU ) ) + ALLOCATE ( ZNORTH_IN ( IIB:IIE , IJE-IHALO_1:IJE , IKU ) ) + ALLOCATE ( ZWEST_IN ( IIB:IIB+IHALO_1 , IJB:IJE , IKU ) ) + ALLOCATE ( ZEAST_IN ( IIE-IHALO_1:IIE , IJB:IJE , IKU ) ) + !$acc enter data create (ZNORTH_IN, ZSOUTH_IN, ZWEST_IN, ZEAST_IN) + ! + ALLOCATE ( ZSOUTH_OUT ( IIB:IIE , 1:IJB-1 , IKU ) ) + ALLOCATE ( ZNORTH_OUT ( IIB:IIE , IJE+1:IJU , IKU ) ) + ALLOCATE ( ZWEST_OUT ( 1:IIB-1 , IJB:IJE , IKU ) ) + ALLOCATE ( ZEAST_OUT ( IIE+1:IIU , IJB:IJE , IKU ) ) + !$acc enter data create (ZNORTH_OUT, ZSOUTH_OUT, ZWEST_OUT, ZEAST_OUT) + + IF (.NOT. GWEST ) THEN + NP_WEST = ( IP-1 -1 ) + 1 + ELSE + NP_WEST = 0 + ENDIF + IF (.NOT. GEAST ) THEN + NP_EAST = ( IP-1 +1 ) + 1 + ELSE + NP_EAST = 0 + ENDIF + IF (.NOT. GSOUTH ) THEN + NP_SOUTH = ( IP-1 -NP1 ) + 1 + ELSE + NP_SOUTH = 0 + ENDIF + IF (.NOT. GNORTH ) THEN + NP_NORTH = ( IP-1 +NP1 ) + 1 + ELSE + NP_NORTH = 0 + ENDIF + + !print*,"PROC=",IP, GWEST,NP_WEST, GEAST,NP_EAST, GSOUTH,NP_SOUTH , GNORTH,NP_NORTH + + GFIRST_INIT_HALO_D = .FALSE. + + END IF + + END SUBROUTINE INIT_HALO_D END MODULE MODD_HALO_D +! ######################### + SUBROUTINE GET_HALO_D(PSRC,HDIR,HNAME) +! ######################### +! +USE MODD_HALO_D + +!USE MODE_MNH_ZWORK, ONLY : GWEST , GEAST, GSOUTH , GNORTH +!USE MODE_MNH_ZWORK, ONLY : IIU,IJU,IKU +!USE MODE_MNH_ZWORK, ONLY : IIB,IJB ,IIE,IJE +!! +!USE MODE_DEVICE +USE MODE_MPPDB +USE MODI_GET_HALO, ONLY : GET_HALO_START_D,GET_HALO_STOP_D +! +IMPLICIT NONE +! +REAL, DIMENSION(:,:,:), INTENT(INOUT) :: PSRC ! variable at t +!$acc declare present (PSRC) +CHARACTER(len=4), OPTIONAL :: HDIR ! to send only halo on X or Y direction +character(len=*), optional, intent(in) :: HNAME ! Name of the field to be added +! +INTEGER :: INB_REQ , IREQ(8) +! +CALL GET_HALO_START_D(PSRC,INB_REQ,IREQ,HDIR) +CALL GET_HALO_STOP_D(PSRC,INB_REQ,IREQ,HDIR) +! +END SUBROUTINE GET_HALO_D +! ######################### + SUBROUTINE GET_HALO_START_D(PSRC,KNB_REQ,KREQ,HDIR) +! ######################### +! +USE MODD_HALO_D + +USE MODE_MNH_ZWORK, ONLY : GWEST , GEAST, GSOUTH , GNORTH +USE MODE_MNH_ZWORK, ONLY : IIU,IJU,IKU +USE MODE_MNH_ZWORK, ONLY : IIB,IJB ,IIE,IJE +! +USE MODD_VAR_ll, ONLY : NMNH_COMM_WORLD +USE MODD_MPIF, ONLY : MPI_STATUSES_IGNORE +USE MODD_PRECISION, ONLY : MNHREAL_MPI +! +USE MODE_DEVICE +USE MODE_MPPDB +! +IMPLICIT NONE +! +REAL, DIMENSION(:,:,:), INTENT(INOUT) :: PSRC ! variable at t +!$acc declare present (PSRC) +INTEGER :: KNB_REQ , KREQ(8) +CHARACTER(len=4), OPTIONAL :: HDIR ! to send only halo on X or Y direction +! +INTEGER :: IERROR ! error return code + +INTEGER,PARAMETER :: IS_WEST=1 , IS_EAST=2, IS_SOUTH=3, IS_NORTH=4 +LOGICAL :: LX , LY +INTEGER :: NB_REQ, IERR +! + +CALL INIT_HALO_D() + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +!$acc data present (ZNORTH_IN, ZSOUTH_IN, ZWEST_IN, ZEAST_IN) & +!$acc present (ZNORTH_OUT, ZSOUTH_OUT, ZWEST_OUT, ZEAST_OUT) + +LX = .FALSE. +LY = .FALSE. + +IF (.NOT. PRESENT(HDIR) ) THEN +LX = .TRUE. +LY = .TRUE. +ELSE +!!$LX = ( HDIR == "01_X" .OR. HDIR == "S0_X" ) +!!$LY = ( HDIR == "01_Y" .OR. HDIR == "S0_Y" ) +LX = ( HDIR == "01_X" .OR. HDIR == "S0_X" .OR. HDIR == "S0_Y" ) +LY = ( HDIR == "01_Y" .OR. HDIR == "S0_Y" .OR. HDIR == "S0_X" ) +!!$print *,"IIB=",IIB," HDIR=",HDIR," LX=",LX," LY=",LY ; call flush(6) +END IF + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +NB_REQ = 0 + +! +! Post the recieve of Zxxxx_IN buffer first via MPI(Gpu_direct) +! + +IF (LX) THEN + IF (.NOT. GWEST) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZWEST_OUT) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_IRECV(ZWEST_OUT,SIZE(ZWEST_OUT),MNHREAL_MPI,NP_WEST-1,1000+IS_EAST,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + END IF + IF (.NOT.GEAST) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZEAST_OUT) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_IRECV(ZEAST_OUT,SIZE(ZEAST_OUT),MNHREAL_MPI,NP_EAST-1,1000+IS_WEST,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF +END IF + +IF (LY) THEN + IF (.NOT.GSOUTH) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZSOUTH_OUT) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_IRECV(ZSOUTH_OUT,SIZE(ZSOUTH_OUT),MNHREAL_MPI,NP_SOUTH-1,1000+IS_NORTH,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF + IF (.NOT.GNORTH) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZNORTH_OUT) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_IRECV(ZNORTH_OUT,SIZE(ZNORTH_OUT),MNHREAL_MPI,NP_NORTH-1,1000+IS_SOUTH,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF +END IF + +! +! Copy the halo(async) on the device PSRC to Zxxxx_IN buffer +! + +IF (LX) THEN + IF (.NOT. GWEST) THEN + !$acc kernels async(IS_WEST) + ZWEST_IN ( IIB:IIB+IHALO_1 , IJB:IJE , : ) = PSRC( IIB:IIB+IHALO_1 , IJB:IJE , : ) + !$acc end kernels + END IF + IF (.NOT.GEAST) THEN + !$acc kernels async(IS_EAST) + ZEAST_IN ( IIE-IHALO_1:IIE , IJB:IJE , : ) = PSRC( IIE-IHALO_1:IIE , IJB:IJE , : ) + !$acc end kernels + ENDIF +END IF + +IF (LY) THEN + IF (.NOT.GSOUTH) THEN + !$acc kernels async(IS_SOUTH) + ZSOUTH_IN ( IIB:IIE , IJB:IJB+IHALO_1 , : ) = PSRC( IIB:IIE , IJB:IJB+IHALO_1 , : ) + !$acc end kernels + ENDIF + IF (.NOT.GNORTH) THEN + !$acc kernels async(IS_NORTH) + ZNORTH_IN ( IIB:IIE , IJE-IHALO_1:IJE , : ) = PSRC( IIB:IIE , IJE-IHALO_1:IJE , : ) + !$acc end kernels + ENDIF +ENDIF + +!$acc wait + +! +! Send Zxxxx_IN buffer via MPI(Gpu_direct) +! +IF (LX) THEN + IF (.NOT. GWEST) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZWEST_IN) +#else + !$acc update host(ZWEST_IN) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_ISEND(ZWEST_IN,SIZE(ZWEST_IN) ,MNHREAL_MPI,NP_WEST-1,1000+IS_WEST,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + END IF + IF (.NOT.GEAST) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZEAST_IN) +#else + !$acc update host(ZEAST_IN) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_ISEND(ZEAST_IN,SIZE(ZEAST_IN) ,MNHREAL_MPI,NP_EAST-1,1000+IS_EAST,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF +END IF + +IF (LY) THEN + IF (.NOT.GSOUTH) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZSOUTH_IN) +#else + !$acc update host(ZSOUTH_IN) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_ISEND(ZSOUTH_IN,SIZE(ZSOUTH_IN) ,MNHREAL_MPI,NP_SOUTH-1,1000+IS_SOUTH,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF + IF (.NOT.GNORTH) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZNORTH_IN) +#else + !$acc update host(ZNORTH_IN) +#endif + NB_REQ = NB_REQ + 1 + CALL MPI_ISEND(ZNORTH_IN,SIZE(ZNORTH_IN) ,MNHREAL_MPI,NP_NORTH-1,1000+IS_NORTH,NMNH_COMM_WORLD,KREQ(NB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF +ENDIF + +!$acc end data + +KNB_REQ = NB_REQ +! +END SUBROUTINE GET_HALO_START_D +! +! ######################### + SUBROUTINE GET_HALO_STOP_D(PSRC,KNB_REQ,KREQ,HDIR) +! ######################### +! +USE MODD_HALO_D + +USE MODE_MNH_ZWORK, ONLY : GWEST , GEAST, GSOUTH , GNORTH +USE MODE_MNH_ZWORK, ONLY : IIU,IJU,IKU +USE MODE_MNH_ZWORK, ONLY : IIB,IJB ,IIE,IJE +! +USE MODD_VAR_ll, ONLY : NMNH_COMM_WORLD +USE MODD_MPIF, ONLY : MPI_STATUSES_IGNORE +USE MODD_PRECISION, ONLY : MNHREAL_MPI +! +USE MODE_DEVICE +USE MODE_MPPDB +! +IMPLICIT NONE +! +REAL, DIMENSION(:,:,:), INTENT(INOUT) :: PSRC ! variable at t +!$acc declare present (PSRC) +INTEGER :: KNB_REQ , KREQ(8) +CHARACTER(len=4), OPTIONAL :: HDIR ! to send only halo on X or Y direction +! +INTEGER :: IERROR ! error return code + +INTEGER,PARAMETER :: IS_WEST=1 , IS_EAST=2, IS_SOUTH=3, IS_NORTH=4 +LOGICAL :: LX , LY +INTEGER :: NB_REQ, IERR +! + +CALL INIT_HALO_D() + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +!$acc data present (ZNORTH_IN, ZSOUTH_IN, ZWEST_IN, ZEAST_IN) & +!$acc present (ZNORTH_OUT, ZSOUTH_OUT, ZWEST_OUT, ZEAST_OUT) + +LX = .FALSE. +LY = .FALSE. + +IF (.NOT. PRESENT(HDIR) ) THEN +LX = .TRUE. +LY = .TRUE. +ELSE +!!$LX = ( HDIR == "01_X" .OR. HDIR == "S0_X" ) +!!$LY = ( HDIR == "01_Y" .OR. HDIR == "S0_Y" ) +LX = ( HDIR == "01_X" .OR. HDIR == "S0_X" .OR. HDIR == "S0_Y" ) +LY = ( HDIR == "01_Y" .OR. HDIR == "S0_Y" .OR. HDIR == "S0_X" ) +!!$print *,"IIB=",IIB," HDIR=",HDIR," LX=",LX," LY=",LY ; call flush(6) +END IF + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +NB_REQ = KNB_REQ + +CALL MPI_WAITALL(NB_REQ,KREQ,MPI_STATUSES_IGNORE,IERR) + +! +! Copy back the Zxxx_OUT buffer recv via MPI(gpu_direct) to PSRC halo +! + +IF (LX) THEN + IF (.NOT.GWEST) THEN +#ifndef MNH_GPUDIRECT + !$acc update device(ZWEST_OUT) async(IS_WEST) +#endif + !$acc kernels async(IS_WEST) + PSRC( 1:IIB-1 , IJB:IJE , : ) = ZWEST_OUT( 1:IIB-1 , IJB:IJE , : ) + !$acc end kernels + ENDIF + IF (.NOT.GEAST) THEN +#ifndef MNH_GPUDIRECT + !$acc update device(ZEAST_OUT) async(IS_EAST) +#endif + !$acc kernels async(IS_EAST) + PSRC( IIE+1:IIU , IJB:IJE , : ) = ZEAST_OUT( IIE+1:IIU , IJB:IJE , : ) + !$acc end kernels + ENDIF +END IF +IF (LY) THEN + IF (.NOT.GSOUTH) THEN +#ifndef MNH_GPUDIRECT + !$acc update device(ZSOUTH_OUT) async(IS_SOUTH) +#endif + !$acc kernels async(IS_SOUTH) + PSRC( IIB:IIE , 1:IJB-1 , : ) = ZSOUTH_OUT( IIB:IIE , 1:IJB-1 , : ) + !$acc end kernels + ENDIF + IF (.NOT.GNORTH) THEN +#ifndef MNH_GPUDIRECT + !$acc update device(ZNORTH_OUT) async(IS_NORTH) +#endif + !$acc kernels async(IS_NORTH) + PSRC( IIB:IIE , IJE+1:IJU , : ) = ZNORTH_OUT ( IIB:IIE , IJE+1:IJU , : ) + !$acc end kernels + ENDIF +END IF +!$acc wait + +!$acc end data +! +END SUBROUTINE GET_HALO_STOP_D !------------------------------------------------------------------------------- ! ######################################## - SUBROUTINE GET_HALO_D(PSRC, HDIR, HNAME) + SUBROUTINE GET_HALO_DD(PSRC, HDIR, HNAME) ! ######################################## ! USE MODD_HALO_D @@ -155,6 +580,11 @@ USE MODE_MNH_ZWORK, ONLY : GWEST , GEAST, GSOUTH , GNORTH USE MODD_CONF, ONLY : NHALO USE MODE_DEVICE USE MODE_MPPDB + +USE MODD_VAR_ll, ONLY : IP,NPROC,NP1,NP2 +USE MODD_VAR_ll, ONLY : NMNH_COMM_WORLD +USE MODD_MPIF, ONLY : MPI_STATUSES_IGNORE +USE MODD_PRECISION, ONLY : MNHREAL_MPI ! IMPLICIT NONE ! @@ -169,20 +599,21 @@ INTEGER, SAVE :: IIB,IJB ! Begining useful area in x,y,z directions INTEGER, SAVE :: IIE,IJE ! End useful area in x,y,z directions INTEGER,SAVE :: IIU,IJU,IKU -INTEGER,SAVE :: IHALO_1 + INTEGER,PARAMETER :: IS_WEST=1 , IS_EAST=2, IS_SOUTH=3, IS_NORTH=4 +INTEGER, SAVE :: IIBX,IJBX ! Extended Begining useful area in x,y,z directions +INTEGER, SAVE :: IIEX,IJEX ! Extended End useful area in x,y,z directions + LOGICAL :: LX , LY -! -!LOGICAL, SAVE :: GFIRST_GET_HALO_D = .TRUE. -! +INTEGER :: INB_REQ , IREQ(8) +INTEGER :: IERR + +if ( NPROC == 1 ) RETURN !$acc data present ( PSRC ) -!JUANCHECK3D IF (GSMONOPROC) RETURN -! -!define _PW_NOINTERM NULLIFY( TZ_PSRC_ll) ! IF (GFIRST_GET_HALO_D ) THEN @@ -195,34 +626,48 @@ IF (GFIRST_GET_HALO_D ) THEN ! IHALO_1 = NHALO-1 ! -#ifndef _PW_NOINTERM - ALLOCATE ( ZSOUTH_IN ( IIB:IIE , IJB:IJB+IHALO_1 , IKU ) ) - ALLOCATE ( ZNORTH_IN ( IIB:IIE , IJE-IHALO_1:IJE , IKU ) ) - ALLOCATE ( ZWEST_IN ( IIB:IIB+IHALO_1 , IJB:IJE , IKU ) ) - ALLOCATE ( ZEAST_IN ( IIE-IHALO_1:IIE , IJB:IJE , IKU ) ) +!!$ IIBX= 1 ; IIEX= IIU ; IJBX= 1 ; IJEX= IJU + IIBX= IIB ; IIEX= IIE ; IJBX= IJB ; IJEX= IJE + + ALLOCATE ( ZSOUTH_IN ( IIBX:IIEX , IJB:IJB+IHALO_1 , IKU ) ) + ALLOCATE ( ZNORTH_IN ( IIBX:IIEX , IJE-IHALO_1:IJE , IKU ) ) + ALLOCATE ( ZWEST_IN ( IIB:IIB+IHALO_1 , IJBX:IJEX , IKU ) ) + ALLOCATE ( ZEAST_IN ( IIE-IHALO_1:IIE , IJBX:IJEX , IKU ) ) !$acc enter data create (ZNORTH_IN, ZSOUTH_IN, ZWEST_IN, ZEAST_IN) ! - ALLOCATE ( ZSOUTH_OUT ( IIB:IIE , 1:IJB-1 , IKU ) ) - ALLOCATE ( ZNORTH_OUT ( IIB:IIE , IJE+1:IJU , IKU ) ) - ALLOCATE ( ZWEST_OUT ( 1:IIB-1 , IJB:IJE , IKU ) ) - ALLOCATE ( ZEAST_OUT ( IIE+1:IIU , IJB:IJE , IKU ) ) + ALLOCATE ( ZSOUTH_OUT ( IIBX:IIEX , 1:IJB-1 , IKU ) ) + ALLOCATE ( ZNORTH_OUT ( IIBX:IIEX , IJE+1:IJU , IKU ) ) + ALLOCATE ( ZWEST_OUT ( 1:IIB-1 , IJBX:IJEX , IKU ) ) + ALLOCATE ( ZEAST_OUT ( IIE+1:IIU , IJBX:IJEX , IKU ) ) !$acc enter data create (ZNORTH_OUT, ZSOUTH_OUT, ZWEST_OUT, ZEAST_OUT) - CALL INIT_ON_HOST_AND_DEVICE(ZSOUTH_IN,-1e99,'GET_HALO_D::ZSOUTH_IN') - CALL INIT_ON_HOST_AND_DEVICE(ZNORTH_IN,-1e99,'GET_HALO_D::ZNORTH_IN') - CALL INIT_ON_HOST_AND_DEVICE(ZWEST_IN,-1e99,'GET_HALO_D::ZWEST_IN') - CALL INIT_ON_HOST_AND_DEVICE(ZEAST_IN,-1e99,'GET_HALO_D::ZEAST_IN') - - CALL INIT_ON_HOST_AND_DEVICE(ZSOUTH_OUT,-1e99,'GET_HALO_D::ZSOUTH_OUT') - CALL INIT_ON_HOST_AND_DEVICE(ZNORTH_OUT,-1e99,'GET_HALO_D::ZNORTH_OUT') - CALL INIT_ON_HOST_AND_DEVICE(ZWEST_OUT,-1e99,'GET_HALO_D::ZWEST_OUT') - CALL INIT_ON_HOST_AND_DEVICE(ZEAST_OUT,-1e99,'GET_HALO_D::ZEAST_OUT') -#endif - + IF (.NOT. GWEST ) THEN + NP_WEST = ( IP-1 -1 ) + 1 + ELSE + NP_WEST = 0 + ENDIF + IF (.NOT. GEAST ) THEN + NP_EAST = ( IP-1 +1 ) + 1 + ELSE + NP_EAST = 0 + ENDIF + IF (.NOT. GSOUTH ) THEN + NP_SOUTH = ( IP-1 -NP1 ) + 1 + ELSE + NP_SOUTH = 0 + ENDIF + IF (.NOT. GNORTH ) THEN + NP_NORTH = ( IP-1 +NP1 ) + 1 + ELSE + NP_NORTH = 0 + ENDIF + + !print*,"PROC=",IP, GWEST,NP_WEST, GEAST,NP_EAST, GSOUTH,NP_SOUTH , GNORTH,NP_NORTH + GFIRST_GET_HALO_D = .FALSE. + END IF - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LX = .FALSE. @@ -232,162 +677,216 @@ IF (.NOT. PRESENT(HDIR) ) THEN LX = .TRUE. LY = .TRUE. ELSE -LX = ( HDIR == "01_X" .OR. HDIR == "S0_X" ) -LY = ( HDIR == "01_Y" .OR. HDIR == "S0_Y" ) + ! + ! Problem of reproductibility in ppm_s0_x/y if only S0_X or S0_Y + ! so add S0_X + S0_Y for ppm_s0* + ! +!!$LX = ( HDIR == "01_X" .OR. HDIR == "S0_X" ) +!!$LY = ( HDIR == "01_Y" .OR. HDIR == "S0_Y" ) +LX = ( HDIR == "01_X" .OR. HDIR == "S0_X" .OR. HDIR == "S0_Y" ) +LY = ( HDIR == "01_Y" .OR. HDIR == "S0_Y" .OR. HDIR == "S0_X" ) +END IF + +!!$LX = .TRUE. +!!$LY = .TRUE. + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +INB_REQ = 0 + +#define MNH_GPUDIRECT +! +! Post the recieve of Zxxxx_IN buffer first via MPI(Gpu_direct) +! + +IF (LX) THEN + IF (.NOT. GWEST) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZWEST_OUT) +#endif + INB_REQ = INB_REQ + 1 + CALL MPI_IRECV(ZWEST_OUT,SIZE(ZWEST_OUT),MNHREAL_MPI,NP_WEST-1,1000+IS_EAST,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + END IF + IF (.NOT.GEAST) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZEAST_OUT) +#endif + INB_REQ = INB_REQ + 1 + CALL MPI_IRECV(ZEAST_OUT,SIZE(ZEAST_OUT),MNHREAL_MPI,NP_EAST-1,1000+IS_WEST,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF +END IF + +IF (LY) THEN + IF (.NOT.GSOUTH) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZSOUTH_OUT) +#endif + INB_REQ = INB_REQ + 1 + CALL MPI_IRECV(ZSOUTH_OUT,SIZE(ZSOUTH_OUT),MNHREAL_MPI,NP_SOUTH-1,1000+IS_NORTH,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF + IF (.NOT.GNORTH) THEN +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZNORTH_OUT) +#endif + INB_REQ = INB_REQ + 1 + CALL MPI_IRECV(ZNORTH_OUT,SIZE(ZNORTH_OUT),MNHREAL_MPI,NP_NORTH-1,1000+IS_SOUTH,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF END IF +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +!Copy the halo on the device PSRC to Zxxxx_IN -!Copy the halo on the device PSRC to Zxxxx_IN and put it in the PSRC copy on the host -#ifndef _PW_NOINTERM IF (LX) THEN IF (.NOT. GWEST) THEN !$acc kernels async(IS_WEST) - ZWEST_IN ( IIB:IIB+IHALO_1 , IJB:IJE , : ) = PSRC( IIB:IIB+IHALO_1 , IJB:IJE , : ) + ZWEST_IN ( IIB:IIB+IHALO_1 , IJBX:IJEX , : ) = PSRC( IIB:IIB+IHALO_1 , IJBX:IJEX , : ) !$acc end kernels - !$acc update host(ZWEST_IN) async(IS_WEST) - END IF + END IF IF (.NOT.GEAST) THEN !$acc kernels async(IS_EAST) - ZEAST_IN ( IIE-IHALO_1:IIE , IJB:IJE , : ) = PSRC( IIE-IHALO_1:IIE , IJB:IJE , : ) + ZEAST_IN ( IIE-IHALO_1:IIE , IJBX:IJEX , : ) = PSRC( IIE-IHALO_1:IIE , IJBX:IJEX , : ) !$acc end kernels - !$acc update host(ZEAST_IN) async(IS_EAST) - ENDIF + ENDIF END IF IF (LY) THEN IF (.NOT.GSOUTH) THEN !$acc kernels async(IS_SOUTH) - ZSOUTH_IN ( IIB:IIE , IJB:IJB+IHALO_1 , : ) = PSRC( IIB:IIE , IJB:IJB+IHALO_1 , : ) + ZSOUTH_IN ( IIBX:IIEX , IJB:IJB+IHALO_1 , : ) = PSRC( IIBX:IIEX , IJB:IJB+IHALO_1 , : ) !$acc end kernels - !$acc update host(ZSOUTH_IN) async(IS_SOUTH) - ENDIF + ENDIF IF (.NOT.GNORTH) THEN !$acc kernels async(IS_NORTH) - ZNORTH_IN ( IIB:IIE , IJE-IHALO_1:IJE , : ) = PSRC( IIB:IIE , IJE-IHALO_1:IJE , : ) + ZNORTH_IN ( IIBX:IIEX , IJE-IHALO_1:IJE , : ) = PSRC( IIBX:IIEX , IJE-IHALO_1:IJE , : ) !$acc end kernels - !$acc update host(ZNORTH_IN) async(IS_NORTH) ENDIF ENDIF !$acc wait + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! Send Zxxxx_IN buffer via MPI(Gpu_direct) or copy to host +! IF (LX) THEN IF (.NOT. GWEST) THEN - PSRC( IIB:IIB+IHALO_1 , IJB:IJE , : ) = ZWEST_IN ( IIB:IIB+IHALO_1 , IJB:IJE , : ) - ENDIF - IF (.NOT.GEAST) THEN - PSRC( IIE-IHALO_1:IIE , IJB:IJE , : ) = ZEAST_IN ( IIE-IHALO_1:IIE , IJB:IJE , : ) - ENDIF -END IF -IF (LY) THEN - IF (.NOT.GSOUTH) THEN - PSRC( IIB:IIE , IJB:IJB+IHALO_1 , : ) = ZSOUTH_IN ( IIB:IIE , IJB:IJB+IHALO_1 , : ) - ENDIF - IF (.NOT.GNORTH) THEN - PSRC( IIB:IIE , IJE-IHALO_1:IJE , : ) = ZNORTH_IN ( IIB:IIE , IJE-IHALO_1:IJE , : ) - ENDIF -ENDIF +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZWEST_IN) #else -IF (LX) THEN - IF (.NOT. GWEST) THEN - !$acc update host(PSRC( IIB:IIB+IHALO_1 , IJB:IJE , : )) - ENDIF + !$acc update host(ZWEST_IN) +#endif + INB_REQ = INB_REQ + 1 + CALL MPI_ISEND(ZWEST_IN,SIZE(ZWEST_IN) ,MNHREAL_MPI,NP_WEST-1,1000+IS_WEST,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + END IF IF (.NOT.GEAST) THEN - !$acc update host(PSRC( IIE-IHALO_1:IIE , IJB:IJE , : )) +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZEAST_IN) +#else + !$acc update host(ZEAST_IN) +#endif + INB_REQ = INB_REQ + 1 + CALL MPI_ISEND(ZEAST_IN,SIZE(ZEAST_IN) ,MNHREAL_MPI,NP_EAST-1,1000+IS_EAST,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif ENDIF END IF + IF (LY) THEN IF (.NOT.GSOUTH) THEN - !$acc update host(PSRC( IIB:IIE , IJB:IJB+IHALO_1 , : )) +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZSOUTH_IN) +#else + !$acc update host(ZSOUTH_IN) +#endif + INB_REQ = INB_REQ + 1 + CALL MPI_ISEND(ZSOUTH_IN,SIZE(ZSOUTH_IN) ,MNHREAL_MPI,NP_SOUTH-1,1000+IS_SOUTH,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif ENDIF IF (.NOT.GNORTH) THEN - !$acc update host(PSRC( IIB:IIE , IJE-IHALO_1:IJE , : )) - ENDIF -ENDIF +#ifdef MNH_GPUDIRECT + !$acc host_data use_device(ZNORTH_IN) +#else + !$acc update host(ZNORTH_IN) #endif -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -if ( present ( hname ) ) then - yname = hname -else - yname = 'PSRC' -end if - -IF (LX .OR. LY) THEN - CALL ADD3DFIELD_ll( TZ_PSRC_ll, PSRC, 'GET_HALO::'//trim( yname ) ) - CALL UPDATE_HALO_ll(TZ_PSRC_ll,IERROR, HDIR=HDIR ) - CALL CLEANLIST_ll(TZ_PSRC_ll) -ELSE - !Necessary to allow comparisons/checks with standard GET_HALO - CALL MPPDB_CHECK(PSRC,"UPDATE_HALO_ll::GET_HALO::"//trim( yname )) + INB_REQ = INB_REQ + 1 + CALL MPI_ISEND(ZNORTH_IN,SIZE(ZNORTH_IN) ,MNHREAL_MPI,NP_NORTH-1,1000+IS_NORTH,NMNH_COMM_WORLD,IREQ(INB_REQ),IERR) +#ifdef MNH_GPUDIRECT + !$acc end host_data +#endif + ENDIF ENDIF -!Copy the halo on the host PSRC to Zxxxx_OUT and put it in the PSRC copy on the device -#ifndef _PW_NOINTERM -IF (LX) THEN - IF (.NOT.GWEST) THEN - ZWEST_OUT( 1:IIB-1 , IJB:IJE , : ) = PSRC( 1:IIB-1 , IJB:IJE , : ) - ENDIF - IF (.NOT.GEAST) THEN - ZEAST_OUT( IIE+1:IIU , IJB:IJE , : ) = PSRC( IIE+1:IIU , IJB:IJE , : ) - ENDIF -END IF -IF (LY) THEN - IF (.NOT.GSOUTH) THEN - ZSOUTH_OUT ( IIB:IIE , 1:IJB-1 , : ) = PSRC( IIB:IIE , 1:IJB-1 , : ) - ENDIF - IF (.NOT.GNORTH) THEN - ZNORTH_OUT ( IIB:IIE , IJE+1:IJU , : ) = PSRC( IIB:IIE , IJE+1:IJU , : ) - ENDIF +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +IF ( INB_REQ > 0 ) THEN + CALL MPI_WAITALL(INB_REQ,IREQ,MPI_STATUSES_IGNORE,IERR) END IF + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! Is update halo + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + IF (LX) THEN IF (.NOT.GWEST) THEN +#ifndef MNH_GPUDIRECT !$acc update device(ZWEST_OUT) async(IS_WEST) +#endif !$acc kernels async(IS_WEST) - PSRC( 1:IIB-1 , IJB:IJE , : ) = ZWEST_OUT( 1:IIB-1 , IJB:IJE , : ) + PSRC( 1:IIB-1 , IJBX:IJEX , : ) = ZWEST_OUT( 1:IIB-1 , IJBX:IJEX , : ) !$acc end kernels ENDIF IF (.NOT.GEAST) THEN +#ifndef MNH_GPUDIRECT !$acc update device(ZEAST_OUT) async(IS_EAST) +#endif !$acc kernels async(IS_EAST) - PSRC( IIE+1:IIU , IJB:IJE , : ) = ZEAST_OUT( IIE+1:IIU , IJB:IJE , : ) + PSRC( IIE+1:IIU , IJBX:IJEX , : ) = ZEAST_OUT( IIE+1:IIU , IJBX:IJEX , : ) !$acc end kernels ENDIF END IF IF (LY) THEN IF (.NOT.GSOUTH) THEN +#ifndef MNH_GPUDIRECT !$acc update device(ZSOUTH_OUT) async(IS_SOUTH) +#endif !$acc kernels async(IS_SOUTH) - PSRC( IIB:IIE , 1:IJB-1 , : ) = ZSOUTH_OUT( IIB:IIE , 1:IJB-1 , : ) + PSRC( IIBX:IIEX , 1:IJB-1 , : ) = ZSOUTH_OUT( IIBX:IIEX , 1:IJB-1 , : ) !$acc end kernels ENDIF IF (.NOT.GNORTH) THEN +#ifndef MNH_GPUDIRECT !$acc update device(ZNORTH_OUT) async(IS_NORTH) +#endif !$acc kernels async(IS_NORTH) - PSRC( IIB:IIE , IJE+1:IJU , : ) = ZNORTH_OUT ( IIB:IIE , IJE+1:IJU , : ) + PSRC( IIBX:IIEX , IJE+1:IJU , : ) = ZNORTH_OUT ( IIBX:IIEX , IJE+1:IJU , : ) !$acc end kernels ENDIF END IF !$acc wait -#else -IF (LX) THEN - IF (.NOT.GWEST) THEN - !$acc update device(PSRC( 1:IIB-1 , IJB:IJE , : )) - ENDIF - IF (.NOT.GEAST) THEN - !$acc update device(PSRC( IIE+1:IIU , IJB:IJE , : )) - ENDIF -END IF -IF (LY) THEN - IF (.NOT.GSOUTH) THEN - !$acc update device(PSRC( IIB:IIE , 1:IJB-1 , : )) - ENDIF - IF (.NOT.GNORTH) THEN - !$acc update device(PSRC( IIB:IIE , IJE+1:IJU , : )) - ENDIF -END IF -#endif !$acc end data -END SUBROUTINE GET_HALO_D +END SUBROUTINE GET_HALO_DD #endif !----------------------------------------------------------------------- ! -- GitLab