Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29273 Discussions

Subroutine vs. Function - segmentation fault

Kamil_Kie
Beginner
1,701 Views
[fortran]program main
  integer :: n
  double precision,pointer :: d(:,:)
  
  n=10000
  allocate(d(n,n))
  call happy(n,d)
  d= sad(n)
  
  print *,"D(1,1) =",d(1,1),"D(n,n) =",d(n,n)
  
  deallocate(d)
  
contains

  subroutine happy(n,d)
    integer :: n
    double precision :: d(:,:)
    d=n*2
    print *,"Hapy :)"
  end subroutine
  
  function sad(n) result (d)
    integer :: n
    double precision :: d(n,n)    
    
    d=n*3
    print *,"Sad :("
  end function
end program[/fortran]
My question is, why program crash on call "sad" function (segmentation fault) when I run it - and why subroutine "happy" work? The second questrion is how to change "sad" function to work well?
0 Kudos
6 Replies
Ron_Green
Moderator
1,701 Views
sad has to return it's RESULT in a temporary, on stack by default. Read this for some insight:

http://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors/

Unlimit your stack.
0 Kudos
Kamil_Kie
Beginner
1,701 Views
So it means that function must have extra space for temporary tables and extra time to copy result from temporary to destination?So using function isimpractical when we have arrays? So better way to work with arrays(as calculatrion result) is use SUBROUTINES than use functions?

I have right?
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,701 Views
>>sad (function)has to return it's RESULT in a temporary, on stack by default.

It doesn't have to do this (temporary on stack)

It cannot use the stack within the function sad (since it is cleaned up on return from sad)
If it uses the stack of the caller (where else should it get stack space from), then if the caller is compiled with heap arrays, then the temporary is heap allocated (iow - .not. has to return on stack).
Also, the compiler optimizer should be able to determine the code generated is:

construct temp for return value (either on stack or heap allocated)
function call to sad with temp asresult
copy temp (result) to destination
destroy temp (result)

And replace this with:

function call to sad with destination as result


N.B. the substitutioncould be made whenever the destination is not an argument to the function (or aliased)
.or.
was an argument to the function call.and. the compiler could determine a non-interference situation

Jim Dempsey
0 Kudos
TimP
Honored Contributor III
1,701 Views
You're partly right, you have constructed an example illustrating how an array valued function can encounter surprising performance problems.
A fairly commonly encountered example is with the use of MATMUL, as compared with BLAS ?GEMM. The latter avoids allocation and use of additional arrays, which has potential serious cache performance effects (when the data set is large enough for efficient BLAS usage, e.g. 20x20).
I would not go so far as to recommend against array valued functions where they might clarify your source code, until you determine there is a serious performance problem.
0 Kudos
Kamil_Kie
Beginner
1,701 Views
I try to summary it:
Functions that return arrays - advantages:
+ clarify source code (?)
Functions that return arrays - disadvantages:
- use extra space for result array
- use extra time for copy result
- unreliable(in example above - stop working for big 'n' - and you must use non standard compiler options or use some system commands(ulimit) to rectify situation)
- unportable (on gfortran it works, on ifort not)
-------------
When we use convenction like this for "array returned function" substitute:
subroutine happy_f(r,n)
Where last letter of subroutine name is "_f" and first argument is always result array. We get the same clarify code as functions but beter performance, portability, memory usage and reliability.
-------------
I'm not experienced fortran programmer, but I must write big part of fotran 95 code. Can you help me and tell -Doesuseaboveconvention for "array return" is a good practice? Or maby you know better way?
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,701 Views
You could alsoclarify with comments

call happy(
r, & ! result
a, b & ! tweedle dee, tweedle dum
)

Or use a function and have the return value be a scalar or logical representative of an error or status

ok = happy(ret,a,b)
if(.not. ok) goto lalaland


Think of C functions where a scalar can be returned (int/size_t/char*,...) but the output array references are passed in the argument list (usually first but not always).

Jim Dempsey
0 Kudos
Reply