Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inlining functions in Fortran

Tags:

inline

fortran

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.

like image 477
marmistrz Avatar asked Feb 22 '17 08:02

marmistrz


2 Answers

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
like image 108
jabirali Avatar answered Oct 23 '22 06:10

jabirali


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.

like image 41
Leigh Orf Avatar answered Oct 23 '22 07:10

Leigh Orf