Section: Implicit vs. Explicit Loops#
Adapted from: gjbex/Fortran-MOOC
This program demonstrates the speed of implicit vs. explicit loops in Fortran.#
The program will take in a command line argument and construct two argument X argument sized matrices composed of random numbers. The program will then compute the following:
\[
\Large Result = \sum \sqrt{X^2 + Y^2}
\]
where:
\(Result\) is the summation result
\(X\) and \(Y\) are command line argument X command line argument sized matrices
program real32_vs_real64
use, intrinsic :: iso_fortran_env, only : error_unit, I8 => INT64, &
SP => REAL32, DP => REAL64
implicit none
integer(kind=I8) :: nr_values
real(kind=SP), dimension(:), allocatable :: x_sp, y_sp
real(kind=SP) :: result
real :: start_time, end_time
integer :: status, i
call get_argument(nr_values)
! implicit loops
allocate (x_sp(nr_values), y_sp(nr_values), stat=status)
if (status /= 0) then
write (unit=error_unit, fmt='(A)') 'error: can not allocate x_sp/y_sp'
stop 1
end if
call random_number(x_sp)
call random_number(y_sp)
call cpu_time(start_time)
result = sum(sqrt(x_sp**2 + y_sp**2))
call cpu_time(end_time)
print '(A, F20.8)', 'Implicit loop time [s]: ', end_time - start_time
print '(A, F20.8)', 'Summation result: ', result
deallocate (x_sp, y_sp)
! explicit loops
allocate (x_sp(nr_values), y_sp(nr_values), stat=status)
if (status /= 0) then
write (unit=error_unit, fmt='(A)') 'error: can not allocate x_sp/y_sp'
stop 1
end if
call random_number(x_sp)
call random_number(y_sp)
call cpu_time(start_time)
result = 0.0_SP
do i = 1, size(x_sp)
result = result + sqrt(x_sp(i)**2 + y_sp(i)**2)
end do
call cpu_time(end_time)
print '(A, F20.8)', 'Explicit loop time [s]: ', end_time - start_time
print '(A, F20.8)', 'Summation result: ', result
deallocate (x_sp, y_sp)
contains
subroutine get_argument(nr_values)
implicit none
integer(Kind=I8), intent(out) :: nr_values
character(len=1024) :: buffer, msg
integer :: status
if (command_argument_count() /= 1) then
write (unit=error_unit, fmt='(A)') 'error: expect number of values'
stop 2
end if
call get_command_argument(1, buffer)
read (buffer, fmt=*, iomsg=msg, iostat=status) nr_values
if (status /= 0) then
write (unit=error_unit, fmt='(2A)') 'error: ', trim(msg)
stop 3
end if
end subroutine get_argument
end program real32_vs_real64
The above program is compiled and run using Fortran Package Manager (fpm):
Build the Program using FPM (Fortran Package Manager)#
import os
root_dir = ""
root_dir = os.getcwd()
code_dir = root_dir + "/" + "Fortran_Code/Section_Implicit_vs_Explicit_Loops"
os.chdir(code_dir)
build_status = os.system("fpm build 2>/dev/null")
Run the Program using FPM (Fortran Package Manager)#
exec_status = os.system("fpm run -- 10 2>/dev/null")
Implicit loop time [s]: 0.00000100
Summation result: 7.26918840
Explicit loop time [s]: 0.00000100
Summation result: 8.26918221
exec_status = os.system("fpm run -- 100 2>/dev/null")
Implicit loop time [s]: 0.00000100
Summation result: 78.46569824
Explicit loop time [s]: 0.00000100
Summation result: 73.05465698
exec_status = os.system("fpm run -- 1000 2>/dev/null")
Implicit loop time [s]: 0.00000300
Summation result: 761.32910156
Explicit loop time [s]: 0.00000200
Summation result: 770.70007324
exec_status = os.system("fpm run -- 10000 2>/dev/null")
Implicit loop time [s]: 0.00001000
Summation result: 7655.58251953
Explicit loop time [s]: 0.00002200
Summation result: 7623.15283203
exec_status = os.system("fpm run -- 100000 2>/dev/null")
Implicit loop time [s]: 0.00010700
Summation result: 76680.54687500
Explicit loop time [s]: 0.00022600
Summation result: 76532.14062500
exec_status = os.system("fpm run -- 1000000 2>/dev/null")
Implicit loop time [s]: 0.00130100
Summation result: 764747.62500000
Explicit loop time [s]: 0.00223100
Summation result: 765129.37500000
exec_status = os.system("fpm run -- 10000000 2>/dev/null")
Implicit loop time [s]: 0.01117000
Summation result: 7670801.00000000
Explicit loop time [s]: 0.02379100
Summation result: 7670755.50000000
exec_status = os.system("fpm run -- 100000000 2>/dev/null")
Implicit loop time [s]: 0.13284096
Summation result: 33554432.00000000
Explicit loop time [s]: 0.27633798
Summation result: 33554432.00000000