Passing array arguments efficiently in GEOS-Chem

From Geos-chem
Jump to navigation Jump to search

On this page we provide strategies to help you write GEOS-Chem code that passes arrays between subroutines in the most efficient manner.

Overview

In many areas of GEOS-Chem, we pass arrays as arguments from one routine to another. But if this is not done properly, it can cause GEOS-Chem to use an excessive amount of memory and take longer to run, especially at very fine resolutions. The following sections explain this issue in more depth:

Technical Description

This very technical description of how Fortran passes arrays to subroutines is taken from the Intel Fortran Compiler Version 11 Manual, p. 1628-1630:

In Fortran, there are two general types of array arguments:

  1. Explicit-shape arrays (introduced with Fortran 77); for example, A(3,4) and B(0:*)
    • These arrays have a fixed rank and extent that is known at compile time.
    • Other dummy argument (receiving) arrays that are not deferred-shape (such as assumed-size arrays) can be grouped with explicit-shape array arguments.
  2. Deferred-shape arrays (introduced with Fortran 95/90); for example, C(:.:)
    • Types of deferred-shape arrays include array pointers and allocatable arrays.
    • Assumed-shape array arguments generally follow the rules about passing deferred-shape array arguments.


When passing arrays as arguments, either the starting (base) address of the array or the address of an array descriptor is passed:

  1. When using explicit-shape (or assumed-size) arrays to receive an array, the starting address of the array is passed.
  2. When using deferred-shape (or assumed-shape) arrays to receive an array, the address of the array descriptor is passed (the compiler creates the array descriptor).


Passing an assumed-shape array or array pointer to an explicit-shape array can slow run-time performance. This is because the compiler needs to create an array temporary for the entire array. The array temporary is created because the passed array may not be contiguous and the receiving (explicit-shape) array requires a contiguous array. When an array temporary is created, the size of the passed array determines whether the impact on slowing run-time performance is slight or severe.



The following table summarizes what happens with the various combinations of array types. The amount of run-time performance inefficiency depends on the size of the array.



Dummy Argument Array Types (i.e. declared in the routine being called)
Actual Argument Array Type
(i.e. declared in the calling routine)
EXPLICIT-SHAPE ARRAYS DEFERRED-SHAPE and ASSUMED-SHAPE ARRAYS
EXPLICIT-SHAPE ARRAYS Result when using this combination: VERY EFFICIENT.
  • Does not use an array temporary.
  • Does not pass an array descriptor.
  • Interface block optional.
Result when using this combination: EFFICIENT.
  • Only allowed for assumed-shape arrays (not deferred-shape arrays).
  • Does not use an array temporary.
  • Passes an array descriptor.
  • Requires an interface block.
DEFERRED-SHAPE and ASSUMED-SHAPE ARRAYS Result when using this combination:
  • When passing an allocatable array, VERY EFFICIENT.
    • Does not use an array temporary.
    • Does not pass an array descriptor.
    • Interface block optional.
  • When not passing an allocatable array (e.g. a POINTER): NOT EFFICIENT.
    • Instead, use allocatable arrays whenever possible.
    • Uses an array temporary.
    • Does not pass an array descriptor.
    • Interface block optional.
Result when using this combination: EFFICIENT.
  • Requires an assumed-shape or array pointer as dummy argument.
  • Does not use an array temporary.
  • Passes an array descriptor.
  • Requires an interface block.

--Bob Y. 13:47, 6 June 2013 (EDT)

In plain English