Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 3/22/2024
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

Implications for Array Copies

Fortran language semantics sometimes require the compiler to make a temporary copy of an array or array slice. Situations where this can occur include:

  • Passing a non-contiguous array to a procedure that does not declare it as assumed-shape

  • Array expressions, especially those involving intrinsic functions RESHAPE, PACK, and MERGE

  • Assignments of arrays where the array appears on both the left and right-hand sides of the assignment

  • Assignments of POINTER arrays

By default, these temporary values are created on the stack and, if large, may result in a stack overflow error at runtime. The size of the stack can be increased, but with limitations dependent on the operating system. If you use compiler option heap-arrays, it tells the compiler to use heap allocation, rather than the stack, for such temporary copies. Heap allocation adds a small amount of overhead when creating and removing the temporary values, but this is usually inconsequential in comparison to the rest of the code.

Performance can be further improved by entirely eliminating the need for a temporary copy. For the first case in the above list, passing a non-contiguous array to a procedure expecting a contiguous array, enabling compiler option check:arg_temp_created will produce a runtime informational message when the compiler determines that the argument being passed is not contiguous. A runtime test is performed and if the argument is contiguous, no copy is made. However, this option will not issue a diagnostic message for other uses of temporary copies.

One way to avoid temporary copies for array arguments is to change the called procedure to declare the array as assumed-shape, with the DIMENSION(:) attribute. Such procedures require an explicit interface to be visible to the caller. This is best provided by placing the called procedure in a module or a CONTAINS section. As an alternative, an INTERFACE block can be declared.

Use of POINTER arrays makes it difficult for the compiler to know if a temporary value can be avoided. Where possible, replace POINTER with ALLOCATABLE, especially as components of derived types. The language definition directs the compiler to assume that ALLOCATABLE arrays are contiguous and that they do not overlap other variables, unlike POINTERs.

Another situation where the temporary values can be created is for automatic arrays, where an array's bounds are dependent on a routine argument, use or host associated variable, or COMMON variable, and the array is a local variable in the procedure. As above, these automatic arrays are created on the stack by default; compiler option heap-arrays creates them on the heap. Consider making such arrays ALLOCATABLE instead; local ALLOCATABLE variables that do not have the SAVE attribute are automatically deallocated when the routine exits. For example, replace:

SUBROUTINE SUB (N)
INTEGER, INTENT(IN) :: N
REAL :: A(N)

with:

SUBROUTINE SUB(N)
INTEGER, INTENT(IN) :: N
REAL, ALLOCATABLE :: A(:)
ALLOCATE (A(N))

See Also