In a Fortran project we use a binary search to find a desired value:
integer function binsearch(tab, el)
implicit none
real, intent(in) :: tab(:), el
integer :: a, b, mid
a = 1
b = size(tab)
do while (b - a > 1)
mid = (a + b)/2
if (el >= tab(mid)) then
a = mid
else
b = mid
endif
! if (el < tab(mid + 1)) exit ! BAD OPTIMIZATION !
enddo
binsearch = a
end function binsearch
Later on we simply use it
foo = binsearch(tab, el)
Unfortunately the surrounding routine is used so heavily, that the BAD OPTIMIZATION
raises the total execution time by a half. So I considered inlining the function to diminish the call cost.
Is it possible to anyhow mark this function for inlining? In C there's the keyword inline
which is a suggestion for the compiler - and is there anything like this in Fortran 2008?
I don't want to copy-paste this for the sake of the code clarity.
In Fortran, there's no direct analogue to inline
in C; it is always up to the compiler which functions are inlined. The most important thing is then to compile the code with a high optimization level to turn on aggressive inlining (e.g. -Ofast
in gfortran, -fast
in ifort). Also, you probably want to turn on "link-time optimization" (-flto
in gfortran, -ipo
in ifort), so that the compiler can inline functions from different source files at link-time if necessary.
However, there are ways to rewrite the code that increases the chance of inlining. One such way would be to explicitly mark the function as pure
(i.e. a function without side-effects), as the implications of this makes it easier for the compiler to optimize the calls to it. In other words:
pure function binsearch(tab, el) result(r)
real, intent(in) :: tab(:), el
integer :: r, a, b, mid
...
end function
if you could rewrite binsearch
as a nested function inside whatever function you're using it from, it is very likely that the compile will either replace the function call to tab
by the function body or a fast goto
statement, even if you don't change the compilation options. In that case:
subroutine some_other_thing()
...
! Do the search
i = binsearch(tab, el)
...
contains
pure function binsearch(tab, el) result(r)
real, intent(in) :: tab(:), el
integer :: r, a, b, mid
...
end function
end subroutine
It depends on the compiler. I can verify that this works for Cray and Intel Fortran compilers, but the statements are slightly different.
Cray compiler:
!dir$ forceinline :: frob
This would force the compiler to inline function frob. You'd place this immediately above the function definition.
Intel compiler:
!dir$ attributes forceinline :: frob
I do not see that gcc/gfortran currently has these options.
Manuals on both compilers cover this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With