The SUBSCRIPTORDER directive rearranges the subscripts of an array. This results in a new array shape, since the directive changes the order of array dimensions in the declaration. All references to the array are correspondingly rearranged to match the new array shape.
Used with discretion, the SUBSCRIPTORDER directive may improve performance by increasing the number of cache hits and the amount of data prefetching. You may have to experiment with this directive until you find the arrangement that yields the most performance benefits. You may find SUBSCRIPTORDER especially useful when porting code originally intended for a non-cached hardware architecture.
In a cached hardware architecture, such as the PowerPC, an entire cache line of data is often loaded into the processor in order to access each data element. Changing the storage arrangement can be used to ensure that consecutively accessed elements are stored adjacently. This may result in a performance improvement, as there are more element accesses for each cache line referenced. Additionally, adjacently storing array elements which are consecutively accessed may help to better exploit the processor's prefetching facility.
.-,--------------------. V | >>-SUBSCRIPTORDER--(----subscriptorder_array-+--)--------------><
where subscriptorder_array is:
.-,---------------------. V | >>-array_name--(----subscriptorder_number-+--)-----------------><
The SUBSCRIPTORDER directive must appear in a scoping unit preceding all declarations and references to the arrays in the subscriptorder_array list. The directive only applies to that scoping unit and must contain at least one array. If multiple scoping units share an array, then you must apply the SUBSCRIPTORDER directive to each of the applicable scoping units with identical subscript arrangements. Examples of methods of array sharing between scoping units include COMMON statements, USE statements, and subroutine arguments.
The lowest subscript number in a subscriptorder_number list must be 1. The highest number must be equal to the number of dimensions in the corresponding array. Every integer number between these two limits, including the limits, signifies a subscript number prior to rearrangement and must be included exactly once in the list.
You must not apply a SUBSCRIPTORDER directive multiple times to a particular array in a scoping unit.
You must maintain array shape conformance in passing arrays as actual arguments to elemental procedures, if one of the arrays appears in a SUBSCRIPTORDER directive. You must also adjust the actual arguments of the SHAPE, SIZE, LBOUND, and UBOUND inquiry intrinsic procedures and of most transformational intrinsic procedures.
You must manually modify data in input data files and in explicit initializations for arrays that appear in the SUBSCRIPTORDER directive.
On arrays to which the COLLAPSE directive is also applied, the COLLAPSE directive always refers to the pre-subscriptorder dimension numbers.
You must not rearrange the last dimension of an assumed-size array.
Example 1: In the following example, the SUBSCRIPTORDER directive is applied to an explicit-shape array and swaps the subscripts in every reference to the array, without affecting the program output.
!IBM* SUBSCRIPTORDER(A(2,1)) INTEGER COUNT/1/, A(3,2) DO J = 1, 3 DO K = 1, 2 ! Inefficient coding: innermost index is accessing rightmost ! dimension. The subscriptorder directive compensates by ! swapping the subscripts in the array's declaration and ! access statements. ! A(J,K) = COUNT PRINT*, J, K, A(J,K) COUNT = COUNT + 1 END DO END DO
Without the directive above, the array shape is (3,2) and the array elements would be stored in the following order:
A(1,1) A(2,1) A(3,1) A(1,2) A(2,2) A(3,2)
With the directive, the array shape is (2,3) and the array elements are stored in the following order:
A(1,1) A(2,1) A(1,2) A(2,2) A(1,3) A(2,3)
For more information on the COLLAPSE directive, see COLLAPSE