Skip to content

Commit

Permalink
Add date_and_time timer.
Browse files Browse the repository at this point in the history
- Add new tests
- Add new examples
- Update README.md
  • Loading branch information
gha3mi committed Jan 2, 2024
1 parent 421ef1a commit ce4ebce
Show file tree
Hide file tree
Showing 16 changed files with 345 additions and 1 deletion.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ call t%timer_stop(nloops, message, print) ! nloops, message and print are option
call t%timer_write(file_name) ! Optionally, write the result to a file
```

### Measuring elapsed time (date_and_time)

To measure the elapsed wall-clock time, use the following:

```fortran
use fortime
type(timer) :: t
call t%dtimer_start()
! Your code or section to be timed
call t%dtimer_stop(nloops, message, print) ! nloops, message and print are optional
call t%dtimer_write(file_name) ! Optionally, write the result to a file
```

### Measuring CPU time

To measure the CPU time consumed by your code, use these functions:
Expand Down
13 changes: 13 additions & 0 deletions example/example5.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
program example5

use fortime

implicit none

type(timer) :: t

call t%dtimer_start()
call sleep(1) ! Perform operations here
call t%dtimer_stop()

end program example5
17 changes: 17 additions & 0 deletions example/example6.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
program example6

use fortime

implicit none

type(timer) :: t
integer :: nl, nloops=3

call t%dtimer_start()
do nl = 1, nloops
call sleep(1) ! Perform operations ntimes
end do
call t%dtimer_stop(nloops = nloops, message = 'Elapsed time:', print = .true.) ! nloops, message and print are optional.
call t%dtimer_write('example/example6_etimes') ! Optionally, write the elapsed time to a file

end program example6
1 change: 1 addition & 0 deletions example/example6_etimes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0000000000000000
43 changes: 42 additions & 1 deletion fpm.toml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,37 @@ name = "test24"
source-dir = "test"
main = "test24.f90"

[[test]]
name = "test25"
source-dir = "test"
main = "test25.f90"

[[test]]
name = "test26"
source-dir = "test"
main = "test26.f90"

[[test]]
name = "test27"
source-dir = "test"
main = "test27.f90"

[[test]]
name = "test28"
source-dir = "test"
main = "test28.f90"

[[test]]
name = "test29"
source-dir = "test"
main = "test29.f90"

[[test]]
name = "test30"
source-dir = "test"
main = "test30.f90"


[[example]]
name = "example1"
source-dir = "example"
Expand All @@ -165,4 +196,14 @@ main = "example3.f90"
[[example]]
name = "example4"
source-dir = "example"
main = "example4.f90"
main = "example4.f90"

[[example]]
name = "example5"
source-dir = "example"
main = "example5.f90"

[[example]]
name = "example6"
source-dir = "example"
main = "example6.f90"
111 changes: 111 additions & 0 deletions src/fortime.f90
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ module fortime
real(rk), private :: mpi_elapsed ! Elapsed MPI time
real(rk) :: mpi_time ! Elapsed time in seconds
#endif

integer, dimension(8), private :: values_start ! Start date and time values
integer, dimension(8), private :: values_end ! End date and time values
integer, dimension(8), private :: values_elapsed ! Elapsed date and time values
real(rk) :: elapsed_dtime ! Elapsed time in seconds
contains
procedure :: timer_start ! Procedure for starting the timer
procedure :: timer_stop ! Procedure for stopping the timer
Expand All @@ -57,6 +62,10 @@ module fortime
procedure :: mtimer_stop ! Procedure for stopping the MPI timer
procedure :: mtimer_write ! Procedure for writing elapsed MPI time to a file
#endif

procedure :: dtimer_start ! Procedure for starting the date_and_time timer
procedure :: dtimer_stop ! Procedure for stopping the date_and_time timer
procedure :: dtimer_write ! Procedure for writing elapsed date_and_time time to a file
end type
!===============================================================================

Expand Down Expand Up @@ -434,6 +443,108 @@ end subroutine mtimer_write
#endif


!===============================================================================
!> author: Seyed Ali Ghasemi
!> Starts the timer by recording the current processor clock value.
!> This value is used to calculate the elapsed time later.
impure subroutine dtimer_start(this)
class(timer), intent(inout) :: this

! Start the timer
call date_and_time(values=this%values_start)

end subroutine dtimer_start
!===============================================================================


!===============================================================================
!> author: Seyed Ali Ghasemi
!> Stops the timer and calculates the elapsed time.
!> Optionally, it can print a message along with the elapsed time.
impure subroutine dtimer_stop(this, nloops, message, print)
class(timer), intent(inout) :: this
integer, intent(in), optional :: nloops
character(*), intent(in), optional :: message
character(:), allocatable :: msg
logical, intent(in), optional :: print
real(rk) :: values_elapsed_sec

! Stop the timer
call date_and_time(values=this%values_end)

! Calculate the elapsed processor ticks
this%values_elapsed = this%values_end - this%values_start

! Convert processor ticks to seconds
if (.not.present(nloops)) &
this%elapsed_dtime = to_seconds(this%values_elapsed)
if ( present(nloops)) &
this%elapsed_dtime = to_seconds(this%values_elapsed) / real(nloops, kind=rk)

! Print the elapsed time
if (.not. present(message)) then
msg = "Elapsed time:"
else
msg = message
end if

if (present(print)) then
if (print) call print_time(this%elapsed_dtime, msg)
else
call print_time(this%elapsed_dtime, msg)
end if

! Deallocate the message
if (allocated(msg)) deallocate(msg)

end subroutine dtimer_stop
!===============================================================================


!===============================================================================
!> author: Seyed Ali Ghasemi
!> Writes the elapsed time to a file.
impure subroutine dtimer_write(this, file_name)
class(timer), intent(in) :: this
character(*), intent(in) :: file_name
logical :: file_exists
integer :: nunit

! Check if the file exists
inquire(file=file_name, exist=file_exists)

! Open the file in appropriate mode
if (file_exists) then
open(newunit=nunit, file=file_name, status='old', action='write', position='append')
else
open(newunit=nunit, file=file_name, status='new', action='write')
end if

! Write the elapsed time to the file
write(nunit, '(g0)') this%elapsed_dtime

! Close the file
close(nunit)

end subroutine dtimer_write
!===============================================================================


!===============================================================================
!> author: Seyed Ali Ghasemi
pure function to_seconds(values) result(seconds)
integer, dimension(8), intent(in) :: values
real(rk) :: seconds

seconds = real(values(3), rk) * 24.0_rk * 60.0_rk * 60.0_rk + &
real(values(5), rk) * 60.0_rk * 60.0_rk + &
real(values(6), rk) * 60.0_rk + &
real(values(7), rk)

end function to_seconds
!===============================================================================


!===============================================================================
!> author: Seyed Ali Ghasemi
impure subroutine print_time(time, message)
Expand Down
21 changes: 21 additions & 0 deletions test/test25.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
program test25

use kinds
use fortime
use forunittest

implicit none

type(timer) :: t
type(unit_test) :: ut


! Elapsed time
call t%dtimer_start()
call sleep(1) ! Perform operations here
call t%dtimer_stop()

call ut%check(res=t%elapsed_dtime, expected=1.0_rk, tol=1.0e-1_rk, msg='test25')

end program test25

25 changes: 25 additions & 0 deletions test/test26.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
program test26

use kinds
use fortime
use forunittest

implicit none

type(timer) :: t
type(unit_test) :: ut
integer :: nl, nloops=3


! Elapsed time with nloops
call t%dtimer_start()
do nl = 1, nloops
call sleep(1) ! Perform operations ntimes
end do
call t%dtimer_stop(nloops = nloops, message = 'Elapsed time:')
call t%dtimer_write('test/test26_etimes') ! Optionally, write the elapsed time to a file

call ut%check(res=t%elapsed_dtime, expected=1.0_rk, tol=1.0e-1_rk, msg='test26')

end program test26

1 change: 1 addition & 0 deletions test/test26_etimes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.000000000000000
25 changes: 25 additions & 0 deletions test/test27.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
program test27

use kinds
use fortime
use forunittest

implicit none

type(timer) :: t
type(unit_test) :: ut
integer :: nl, nloops=3


! Elapsed time with nloops
call t%dtimer_start()
do nl = 1, nloops
call sleep(1) ! Perform operations ntimes
end do
call t%dtimer_stop(message = 'Elapsed time:')
call t%dtimer_write('test/test27_etimes') ! Optionally, write the elapsed time to a file

call ut%check(res=t%elapsed_dtime, expected=real(nloops,rk)*1.0_rk, tol=1.0e-1_rk, msg='test27')

end program test27

1 change: 1 addition & 0 deletions test/test27_etimes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.000000000000000
21 changes: 21 additions & 0 deletions test/test28.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
program test28

use kinds
use fortime
use forunittest

implicit none

type(timer) :: t
type(unit_test) :: ut


! Elapsed time
call t%dtimer_start()
call sleep(1) ! Perform operations here
call t%dtimer_stop(print=.false.)

call ut%check(res=t%elapsed_dtime, expected=1.0_rk, tol=1.0e-1_rk, msg='test28')

end program test28

25 changes: 25 additions & 0 deletions test/test29.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
program test29

use kinds
use fortime
use forunittest

implicit none

type(timer) :: t
type(unit_test) :: ut
integer :: nl, nloops=3


! Elapsed time with nloops
call t%dtimer_start()
do nl = 1, nloops
call sleep(1) ! Perform operations ntimes
end do
call t%dtimer_stop(nloops = nloops, message = 'Elapsed time:', print=.false.)
call t%dtimer_write('test/test29_etimes') ! Optionally, write the elapsed time to a file

call ut%check(res=t%elapsed_dtime, expected=1.0_rk, tol=1.0e-1_rk, msg='test29')

end program test29

1 change: 1 addition & 0 deletions test/test29_etimes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.000000000000000
25 changes: 25 additions & 0 deletions test/test30.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
program test30

use kinds
use fortime
use forunittest

implicit none

type(timer) :: t
type(unit_test) :: ut
integer :: nl, nloops=3


! Elapsed time with nloops
call t%dtimer_start()
do nl = 1, nloops
call sleep(1) ! Perform operations ntimes
end do
call t%dtimer_stop(message = 'Elapsed time:', print=.false.)
call t%dtimer_write('test/test30_etimes') ! Optionally, write the elapsed time to a file

call ut%check(res=t%elapsed_dtime, expected=real(nloops,rk)*1.0_rk, tol=1.0e-1_rk, msg='test30')

end program test30

1 change: 1 addition & 0 deletions test/test30_etimes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.000000000000000

0 comments on commit ce4ebce

Please sign in to comment.