!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ! profile.F90 - part of the Community Ice Sheet Model (CISM) ! !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ! Copyright (C) 2005-2014 ! CISM contributors - see AUTHORS file for list of contributors ! ! This file is part of CISM. ! ! CISM is free software: you can redistribute it and/or modify it ! under the terms of the Lesser GNU General Public License as published ! by the Free Software Foundation, either version 3 of the License, or ! (at your option) any later version. ! ! CISM is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! Lesser GNU General Public License for more details. ! ! You should have received a copy of the Lesser GNU General Public License ! along with CISM. If not, see . ! !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #ifdef HAVE_CONFIG_H #include "config.inc" #endif !> module for profiling programs !! \author Magnus Hagdorn !! \date January 2005 module profile #if (defined CCSMCOUPLED || defined CESMTIMERS) use perf_mod use parallel #endif use glimmer_global, only: dp implicit none #if (defined CCSMCOUPLED || defined CESMTIMERS) logical, public :: output_thispe = .false. #endif integer, private :: current_unit = 200 integer, private,parameter :: max_prof = 100 !> the profiling type type profile_type integer :: profile_unit=0 !< file unit to be written to real(dp) :: start_time !< CPU time at start of log integer :: nump=0 !< number of profiles real(dp), dimension(max_prof) :: pstart,ptotal !< for each log store start and totals character(len=50), dimension(max_prof) :: pname !< name for each profile end type profile_type contains !> initialise a profile subroutine profile_init(prof,name) implicit none type(profile_type), intent(out) :: prof !< structure storing profile definitions character(len=*), intent(in) :: name !< name of file ! local variables character(len=8) :: date character(len=10) :: time prof%profile_unit = current_unit current_unit = current_unit + 1 #if (defined PROFILING && ! defined CCSMCOUPLED && ! defined CESMTIMERS) prof%pstart(:) = 0. prof%ptotal(:) = 0. call cpu_time(prof%start_time) call date_and_time (date, time) open(unit=prof%profile_unit,file=name,status='unknown') write(unit=prof%profile_unit,fmt="(a,a4,'-',a2,'-',a2,' ',a2,':',a2,':',a6)") '# Started profile on ',& date(1:4),date(5:6),date(7:8),time(1:2),time(3:4),time(5:10) #endif #if (! defined CCSMCOUPLED && defined CESMTIMERS) call t_initf("perf_in", mpicom=comm, MasterTask=main_task) #endif end subroutine profile_init !> register a new series of meassurements function profile_register(prof,msg) use glimmer_log implicit none type(profile_type) :: prof !< structure storing profile definitions character(len=*), intent(in) :: msg !< the message to be associated integer profile_register prof%nump = prof%nump+1 if (prof%nump > max_prof) then call write_log('Maximum number of profiles reached',type=GM_FATAL, & file=__FILE__,line=__LINE__) end if profile_register = prof%nump prof%pname(prof%nump) = trim(msg) end function profile_register !> start profiling subroutine profile_start(prof,profn) implicit none type(profile_type) :: prof !< structure storing profile definitions integer, intent(in) :: profn !< the profile ID #if (defined PROFILING && ! defined CCSMCOUPLED && ! defined CESMTIMERS) call cpu_time(prof%pstart(profn)) #endif #if (defined CCSMCOUPLED || defined CESMTIMERS) call t_startf(prof%pname(profn)) #endif end subroutine profile_start !> stop profiling subroutine profile_stop(prof,profn) implicit none type(profile_type) :: prof !< structure storing profile definitions integer, intent(in) :: profn !< the profile ID #if (defined PROFILING && ! defined CCSMCOUPLED && ! defined CESMTIMERS) real(dp) :: t call cpu_time(t) prof%ptotal(profn) = prof%ptotal(profn) + t-prof%pstart(profn) #endif #if (defined CCSMCOUPLED || defined CESMTIMERS) call t_stopf(prof%pname(profn)) #endif end subroutine profile_stop !> log a message to profile subroutine profile_log(prof,profn,msg) implicit none type(profile_type) :: prof !< structure storing profile definitions integer, intent(in) :: profn !< the profile ID character(len=*), intent(in), optional :: msg !< message to be written to profile #if (defined PROFILING && ! defined CCSMCOUPLED && ! defined CESMTIMERS) real(dp) :: t call cpu_time(t) if (present(msg)) then write(prof%profile_unit,*) t-prof%start_time,prof%ptotal(profn),profn,trim(msg)//' '//trim(prof%pname(profn)) else write(prof%profile_unit,*) t-prof%start_time,prof%ptotal(profn),profn,trim(prof%pname(profn)) end if prof%ptotal(profn) = 0. prof%pstart(profn) = 0. #endif end subroutine profile_log !> close profile subroutine profile_close(prof) implicit none type(profile_type), intent(in) :: prof !< structure storing profile definitions #if (defined PROFILING && ! defined CCSMCOUPLED && ! defined CESMTIMERS) ! local variables character(len=8) :: date character(len=10) :: time real(dp) :: t call cpu_time(t) call date_and_time (date, time) write(prof%profile_unit,*) '# total elapse cpu time: ',t-prof%start_time write(unit=prof%profile_unit,fmt="(a,a4,'-',a2,'-',a2,' ',a2,':',a2,':',a6)") '# Finished profile on ',& date(1:4),date(5:6),date(7:8),time(1:2),time(3:4),time(5:10) close(prof%profile_unit) #endif #if (! defined CCSMCOUPLED && defined CESMTIMERS) integer :: ewrank, nsrank, nstasks ! Sample performance data from process in middle of ! computational domain ewrank = mod(this_rank,ProcsEW) nsrank = this_rank/ProcsEW nstasks = tasks/ProcsEW if ((ewrank .eq. (ProcsEW+1)/2) .and. (nsrank .eq. (nstasks+1)/2)) then call t_prf('cism_timing', num_outpe=1, global_stats=.true., & output_thispe=.true.) else call t_prf('cism_timing', num_outpe=1, global_stats=.true.) endif call t_finalizef () #endif end subroutine profile_close #if (! defined CCSMCOUPLED && ! defined CESMTIMERS) subroutine t_startf(event, handle) integer,parameter :: SHR_KIND_I8 = selected_int_kind (13) ! 8 byte integer character(len=*), intent(in) :: event integer(shr_kind_i8), optional :: handle return end subroutine t_startf subroutine t_stopf(event, handle) integer,parameter :: SHR_KIND_I8 = selected_int_kind (13) ! 8 byte integer character(len=*), intent(in) :: event integer(shr_kind_i8), optional :: handle return end subroutine t_stopf subroutine t_adj_detailf(detail_adjustment) integer, intent(in) :: detail_adjustment return end subroutine t_adj_detailf #endif end module profile