module times INTEGER,PRIVATE,save :: Last_Count=0 REAL, PRIVATE,save :: Last_cpuCount=0 logical, PRIVATE,save :: AllTimer_IsActive=.FALSE. INTEGER, parameter :: nb_timer = 4 INTEGER, parameter :: timer_caldyn = 1 INTEGER, parameter :: timer_vanleer = 2 INTEGER, parameter :: timer_dissip = 3 INTEGER, parameter :: timer_physic = 4 INTEGER, parameter :: stopped = 1 INTEGER, parameter :: running = 2 INTEGER, parameter :: suspended = 3 INTEGER :: max_size REAL, ALLOCATABLE, DIMENSION(:,:,:) :: timer_table REAL, ALLOCATABLE, DIMENSION(:,:,:) :: timer_table_sqr INTEGER, ALLOCATABLE, DIMENSION(:,:,:) :: timer_iteration REAL, ALLOCATABLE, DIMENSION(:,:,:) :: timer_average REAL, ALLOCATABLE, DIMENSION(:,:,:) :: timer_delta REAL, ALLOCATABLE,DIMENSION(:) :: timer_running, last_time INTEGER, ALLOCATABLE,DIMENSION(:) :: timer_state CONTAINS SUBROUTINE init_timer USE parallel_lmdz IMPLICIT NONE INCLUDE "dimensions.h" INCLUDE "paramet.h" max_size=jjm+1 allocate(timer_table(max_size,nb_timer,0:mpi_size-1)) allocate(timer_table_sqr(max_size,nb_timer,0:mpi_size-1)) allocate(timer_iteration(max_size,nb_timer,0:mpi_size-1)) allocate(timer_average(max_size,nb_timer,0:mpi_size-1)) allocate(timer_delta(max_size,nb_timer,0:mpi_size-1)) allocate(timer_running(nb_timer)) allocate(timer_state(nb_timer)) allocate(last_time(nb_timer)) timer_table(:,:,:)=0 timer_table_sqr(:,:,:)=0 timer_iteration(:,:,:)=0 timer_average(:,:,:)=0 timer_delta(:,:,:)=0 timer_state(:)=stopped END SUBROUTINE init_timer SUBROUTINE start_timer(no_timer) IMPLICIT NONE INTEGER :: no_timer IF (AllTimer_IsActive) THEN IF (timer_state(no_timer)/=stopped) THEN CALL abort_gcm("times","start_timer :: timer is already running or suspended",1) else timer_state(no_timer)=running endif timer_running(no_timer)=0 CALL cpu_time(last_time(no_timer)) endif END SUBROUTINE start_timer SUBROUTINE suspend_timer(no_timer) IMPLICIT NONE INTEGER :: no_timer IF (AllTimer_IsActive) THEN IF (timer_state(no_timer)/=running) THEN CALL abort_gcm("times","suspend_timer :: timer is not running",1) else timer_state(no_timer)=suspended endif timer_running(no_timer)=timer_running(no_timer)-last_time(no_timer) CALL cpu_time(last_time(no_timer)) timer_running(no_timer)=timer_running(no_timer)+last_time(no_timer) endif END SUBROUTINE suspend_timer SUBROUTINE resume_timer(no_timer) IMPLICIT NONE INTEGER :: no_timer IF (AllTimer_IsActive) THEN IF (timer_state(no_timer)/=suspended) THEN CALL abort_gcm("times","resume_timer :: timer is not suspended",1) else timer_state(no_timer)=running endif CALL cpu_time(last_time(no_timer)) endif END SUBROUTINE resume_timer SUBROUTINE stop_timer(no_timer) USE parallel_lmdz IMPLICIT NONE INTEGER :: no_timer INTEGER :: N REAL :: V,V2 IF (AllTimer_IsActive) THEN IF (timer_state(no_timer)/=running) THEN CALL abort_gcm("times","stop_timer :: timer is not running",1) else timer_state(no_timer)=stopped endif timer_running(no_timer)=timer_running(no_timer)-last_time(no_timer) CALL cpu_time(last_time(no_timer)) timer_running(no_timer)=timer_running(no_timer)+last_time(no_timer) timer_table(jj_nb,no_timer,mpi_rank)=timer_table(jj_nb,no_timer,mpi_rank)+timer_running(no_timer) timer_table_sqr(jj_nb,no_timer,mpi_rank)=timer_table_sqr(jj_nb,no_timer,mpi_rank)+timer_running(no_timer)**2 timer_iteration(jj_nb,no_timer,mpi_rank)=timer_iteration(jj_nb,no_timer,mpi_rank)+1 timer_average(jj_nb,no_timer,mpi_rank)=timer_table(jj_nb,no_timer,mpi_rank)/timer_iteration(jj_nb,no_timer,mpi_rank) IF (timer_iteration(jj_nb,no_timer,mpi_rank)>=2) THEN N=timer_iteration(jj_nb,no_timer,mpi_rank) V2=timer_table_sqr(jj_nb,no_timer,mpi_rank) V=timer_table(jj_nb,no_timer,mpi_rank) timer_delta(jj_nb,no_timer,mpi_rank)=sqrt(ABS(V2-V*V/N)/(N-1)) else timer_delta(jj_nb,no_timer,mpi_rank)=0 endif endif END SUBROUTINE stop_timer SUBROUTINE allgather_timer USE parallel_lmdz USE lmdz_mpi IMPLICIT NONE INTEGER :: ierr INTEGER :: data_size REAL, ALLOCATABLE,DIMENSION(:,:) :: tmp_table IF (using_mpi) THEN IF (AllTimer_IsActive) THEN allocate(tmp_table(max_size,nb_timer)) data_size=max_size*nb_timer tmp_table(:,:)=timer_table(:,:,mpi_rank) CALL mpi_allgather(tmp_table(1,1),data_size,MPI_REAL_LMDZ,timer_table(1,1,0),data_size,MPI_REAL_LMDZ,COMM_LMDZ,ierr) tmp_table(:,:)=timer_table_sqr(:,:,mpi_rank) CALL mpi_allgather(tmp_table(1,1),data_size,MPI_REAL_LMDZ,timer_table_sqr(1,1,0),data_size,MPI_REAL_LMDZ,COMM_LMDZ,ierr) deallocate(tmp_table) endif ENDIF ! using_mpi END SUBROUTINE allgather_timer SUBROUTINE allgather_timer_average USE parallel_lmdz USE lmdz_mpi IMPLICIT NONE INTEGER :: ierr INTEGER :: data_size REAL, ALLOCATABLE,DIMENSION(:,:),target :: tmp_table INTEGER, ALLOCATABLE,DIMENSION(:,:),target :: tmp_iter INTEGER :: istats IF (using_mpi) THEN IF (AllTimer_IsActive) THEN allocate(tmp_table(max_size,nb_timer)) allocate(tmp_iter(max_size,nb_timer)) data_size=max_size*nb_timer tmp_table(:,:)=timer_average(:,:,mpi_rank) CALL mpi_allgather(tmp_table(1,1),data_size,MPI_REAL_LMDZ,timer_average(1,1,0),data_size,MPI_REAL_LMDZ,COMM_LMDZ,ierr) tmp_table(:,:)=timer_delta(:,:,mpi_rank) CALL mpi_allgather(tmp_table(1,1),data_size,MPI_REAL_LMDZ,timer_delta(1,1,0),data_size,MPI_REAL_LMDZ,COMM_LMDZ,ierr) tmp_iter(:,:)=timer_iteration(:,:,mpi_rank) CALL mpi_allgather(tmp_iter(1,1),data_size,MPI_INTEGER,timer_iteration(1,1,0),data_size,MPI_INTEGER,COMM_LMDZ,ierr) deallocate(tmp_table) endif ENDIF ! using_mpi END SUBROUTINE allgather_timer_average SUBROUTINE InitTime IMPLICIT NONE INTEGER :: count,count_rate,count_max AllTimer_IsActive=.TRUE. IF (AllTimer_IsActive) THEN CALL system_clock(count,count_rate,count_max) CALL cpu_time(Last_cpuCount) Last_Count=count endif END SUBROUTINE InitTime function DiffTime() IMPLICIT NONE double precision :: DiffTime INTEGER :: count,count_rate,count_max CALL system_clock(count,count_rate,count_max) IF (Count>=Last_Count) THEN DiffTime=(1.*(Count-last_Count))/count_rate else DiffTime=(1.*(Count-last_Count+Count_max))/count_rate endif Last_Count=Count END FUNCTION DiffTime function DiffCpuTime() IMPLICIT NONE REAL :: DiffCpuTime REAL :: Count CALL cpu_time(Count) DiffCpuTime=Count-Last_cpuCount Last_cpuCount=Count END FUNCTION DiffCpuTime END MODULE times