Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Section: Implicit vs. Explicit Loops

---
jupytext:
  formats: md:myst
  text_representation:
    extension: .md
    format_name: myst
kernelspec:
  display_name: Python 3
  language: python
  name: python3
---

Section: Implicit vs. Explicit Loops

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:

Result=X2+Y2\Large Result = \sum \sqrt{X^2 + Y^2}

where:
ResultResult is the summation result
XX and YY 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.00000200
Summation result:           9.57156563
Explicit loop time [s]:           0.00000100
Summation result:           8.58767700
exec_status = os.system("fpm run -- 100 2>/dev/null")
Implicit loop time [s]:           0.00000100
Summation result:          82.67105103
Explicit loop time [s]:           0.00000100
Summation result:          78.12156677
exec_status = os.system("fpm run -- 1000 2>/dev/null")
Implicit loop time [s]:           0.00000300
Summation result:         738.62194824
Explicit loop time [s]:           0.00000400
Summation result:         779.73486328
exec_status = os.system("fpm run -- 10000 2>/dev/null")
Implicit loop time [s]:           0.00001100
Summation result:        7668.53564453
Explicit loop time [s]:           0.00002200
Summation result:        7716.35302734
exec_status = os.system("fpm run -- 100000 2>/dev/null")
Implicit loop time [s]:           0.00010800
Summation result:       76268.64062500
Explicit loop time [s]:           0.00022100
Summation result:       76432.85156250
exec_status = os.system("fpm run -- 1000000 2>/dev/null")
Implicit loop time [s]:           0.00211100
Summation result:      765269.12500000
Explicit loop time [s]:           0.00220800
Summation result:      765385.31250000
exec_status = os.system("fpm run -- 10000000 2>/dev/null")
Implicit loop time [s]:           0.02267501
Summation result:     7671492.50000000
Explicit loop time [s]:           0.02569100
Summation result:     7669864.50000000
exec_status = os.system("fpm run -- 100000000 2>/dev/null")
Implicit loop time [s]:           0.10609502
Summation result:    33554432.00000000
Explicit loop time [s]:           0.23883396
Summation result:    33554432.00000000