Dear Damian,
Thank you for your interest. I have added two loops to the earlier code, so now
there are four (nested) loops. The first two loops compare the time of simple
arithmetic and ieee_next_after as described in the original email. The third
and fourth loops are the absolute timing tests that you requested.
The third loop in the appended code iterates over the 32-bit integers and at
each iteration a simple arithmetic operation is performed (that cannot be
optimized away). The fourth loop iterates over the 32-bit reals from
-huge(0.0_real32) to huge(0.0_real32) by way of the ieee_next_after function.
The timings are reported and again we observe the factor of about 200
difference. Compiling with `gfortran -O5` I get 3.9 seconds for the third loop
and 883 seconds for the fourth loop on my Intel i7-1165G7.
Compiling with `-O0` makes no significant difference to the times for
ieee_next_after, but the simple arithmetic tests take longer by about a factor
of two. Nothing unusual there.
Revised code here:
program main
!..use and access
use iso_fortran_env, only : int32, real32, real64
use ieee_arithmetic
implicit none
!..data
integer, parameter :: m=10000, n=10000
integer :: i, j
integer (kind=int32) :: i32, j32
real (kind=real64) :: tim0, tim1, t0, r
real (kind=real32) :: t32, r32
!..executable part
r = 0
call cpu_time (tim0)
do i = 0, m-1
call random_number (t0)
do j = 0, n-1
t0 = t0*(1-epsilon(t0))
r = r+t0
end do
end do
call cpu_time (tim1)
write (*,*) 'simple arithmetic:', tim1-tim0, r
r = 0
call cpu_time (tim0)
do i = 0, m-1
call random_number (t0)
do j = 0, n-1
t0 = ieee_next_after(t0,0.0_real64)
r = r+t0
end do
end do
call cpu_time (tim1)
write (*,*) 'ieee_next_after:', tim1-tim0, r
j32 = huge(0_int32)
i32 = -j32-1
r32 = 0
call cpu_time (tim0)
do while (i32.ne.j32)
r32 = -r32+i32
i32 = i32+1
end do
call cpu_time (tim1)
write (*,*) '2^32 simple arithmetic:', tim1-tim0, r32
t32 = huge(0.0_real32)
r32 = -t32
call cpu_time (tim0)
do while (r32.ne.t32)
r32 = ieee_next_after(r32,t32)
end do
call cpu_time (tim1)
write (*,*) '2^32 ieee_next_after:', tim1-tim0, r32
stop
end program main
Bas Braams
----- Original Message -----
From: "Damian McGuckin" <[email protected]>
To: "B J Braams" <[email protected]>
Cc: "bug-gcc" <[email protected]>
Sent: Sunday, 10 August, 2025 14:27:14
Subject: Re: Very high cost of ieee_next_after function
Can you please write a fortran program which uses real (real*4 or 32-bit
real) and, starting from negative infinity, uses nextafterf to step
through every single real up to positive infinity. How long does this
take please?
Thanks - Damian