Developer Guide and Reference

ID 767251
Date 10/31/2024
Public
Document Table of Contents

LINEAR Clause

Parallel Directive Clause: Specifies that all variables in a list are private to a SIMD lane and that they have a linear relationship within the iteration space of a loop.

Syntax

LINEAR (linear-list [: linear-modifier [, linear-modifier]])

-or deprecated form-

LINEAR (old-linear-list[: linear-step])

linear-list

Is a comma-separated list of one or more integer variables or dummy arguments. If the clause appears in a declarative directive, linear-list items must be dummy arguments of the procedure that will be invoked concurrently on each SIMD lane.

List items must be scalar and of type integer, unless the linear-modifier REF is specified, in which case list items can be dummy arguments of any type and rank. Each list item must comply with PRIVATE clause semantics.

List items cannot have the POINTER attribute or be Cray* pointers.

linear-modifier

Is step-modifier or modifier.

step-modifier

Is STEP (linear-step) or linear-step. linear-step must appear if STEP appears. If step-modifier is present, it must be the first (leftmost) linear-modifer specified.

linear-step

Is a compile-time positive, integer, scalar constant expression. If linear-step is not specified, it is assumed to be 1.

modifier

Is one of the following:

  • REF

    Specifies that the storage location of each linear-list item on each lane corresponds to an array at the storage location upon entry to the function indexed by the logical number of the lane times linear-step. The REF modifier can only appear in a LINEAR clause of a declarative directive.

    The referenced values passed into the routine (which forms a vector for calculations) are located sequentially, like in an array, with the distance between elements equal to linear-step.

    This modifier can be used only for dummy arrays passed by reference. The dummy arrays can be explicit shape or assumed shape, and they can have the ALLOCATABLE attribute.

  • VAL

    Specifies that the value of each linear-list item on each lane corresponds to the value of the linear-list item upon entry to the function plus the logical number of the lane times linear-step.

    On each iteration of the loop from which the routine is called, the value of the parameter can be calculated as (value_on_previous_iteration + linear-step).

  • UVAL

    Similar to VAL, but each invocation uses the same storage location for each SIMD lane. This storage location is updated with the final value of the logically last lane. It differs from VAL as follows:

    • For VAL, a vector of addresses (references) is passed to the vector variant of the routine.

    • For UVAL, only one address (reference) is passed, which may improve performance.

    This modifier can be used only for dummy arguments passed by reference. A UVAL modifier can only appear in a LINEAR clause of a declarative directive.

If modifier is not specified or it is VAL or UVAL, the value of each linear-list item on each lane corresponds to the value of the linear-list item upon entry to the function plus the logical number of the lane times linear-step.

You can only use REF or VAL if the linear-list item is a dummy argument without the Fortran Standard VALUE attribute.

old-linear-list

Is one of the following:

  • linear-list

  • modifier (linear-list)

A LINEAR clause can specify at most one step-modifier and one modifier. Multiple LINEAR clauses can be used to specify different values for linear-step and/or modifiers. The linear-step expression must be invariant (must not be changed) during the execution of the associated construct. Multiple LINEAR clauses are merged as a union.

The value of the linear-list item on a given iteration is equal to the value of the original list item plus the logical number of the iteration times linear-step. The value corresponding to the sequentially last iteration of the associated loops is assigned to the original linear-list item. If modifier is not REF and the linear-list item has the ALLOCATABLE attribute, in the sequentially last iteration the allocation status of the linear-list item must be allocated upon completion of that iteration.

A linear-list item in a LINEAR clause cannot appear in any other data scope attribute clause, in another LINEAR clause in the same directive, or more than once in linear-list. For a list of data scope attribute clauses, see the first table in Clauses Used in Multiple OpenMP* Fortran Directives.

If a linear-list item is a dummy argument without the Fortran Standard VALUE attribute and the REF modifier is not specified, then a read of the linear-list item must be executed before any writes to the linear-list item.

If a LINEAR clause appears in a directive that also contains a REDUCTION clause with the INSCAN modifier, only a loop iteration variable of a loop associated with the construct can appear as a linear-list item in the LINEAR clause.

The REF modifier is very important because Fortran passes dummy arguments by reference. By default, the compiler places consecutive addresses in a vector register, which leads to an inefficient gather of the addresses.

In the following example, linear(x, y:ref) tells the compiler that the 4 addresses for the dummy argument x are consecutive, and the 4 addresses for the dummy argument y are consecutive, so the code only needs to dereference x and y once each and then copy consecutive values to vector registers.

subroutine test_linear(x, y)
!$omp declare simd (test_linear) linear(x, y:ref)    ! arguments by reference
    real(8),intent(in)  :: x(4)
    real(8),intent(out) :: y(4)  
    y = 1. + sin(x)**3
end subroutine test_linear
…                               ! procedure that calls test_linear
interface                       ! test_linear needs an explicit interface
…
do j = 1,n
     call test_linear(a(j), b(j))    ! loop vectorized via qopenmp-simd
enddo
…

Example

Consider the following:

! universal but slowest definition; it matches the use of 
!   func in loops 1, 2, and 3:
!$OMP DECLARE SIMD  
!                  
! matches the use of func in loop 1:
!$OMP DECLARE SIMD LINEAR(in1) LINEAR (in2: REF) UNIFORM(mul)  
!    
! matches the use of func in loops 2 and 3:
!$OMP DECLARE SIMD LINEAR (in2: REF) 
!                   
! matches the use of func in loop 2:
!$OMP DECLARE SIMD LINEAR (in2: REF) LINEAR(mul)
!        
! matches the use of func in loop 3:
!$OMP DECLARE SIMD LINEAR (in2: STEP(2), VAL)                

function func(in1, in2, mul)
integral   in1
integral   in2
integral   mul
...
integral a, k
integral b(100)
integral c(100)
integral ndx(100)
...

The following are the loop examples referenced above.

!loop 1
!$OMP SIMD
   DO i=1,100 
      c(i) = func(a + i, b(i), mul) ! the value of the 1st parameter is  
                                    !   changed linearly, the 2nd parameter 
                                    !   reference is changed linearly, the 3rd 
                                    !   parameter is not changed
   END DO

!loop 2
!$OMP SIMD
   DO i=1,100
      c(i) = func(b(ndx(i)), b(i), i + 1 ! the value of the 1st parameter is 
                                         !   unpredictable, the 2nd reference  
                                         !   is changed linearly, the 3rd  
                                         !   parameter is changed linearly
   END DO

!loop 3
!$OMP SIMD
   DO i=1,100 
      k = i * 2                       ! during vectorization, private variables  
      c(i) = func(b(ndx(i)), k, b(i)) !     are transformed into arrays: 
                                      !     k -> k_vec(simdlen)
                                      ! the value of the 1st parameter is 
                                      ! unpredictable, for the 2nd parameter 
                                      ! both value and reference to its 
                                      ! location can be considered linear,
                                      ! the value for the 3rd parameter is 
                                      ! unpredictable 
                                      !
                                      ! the !$OMP DECLARE SIMD LINEAR(VAL(in2:2)))  
   END DO                             !     will be chosen from the two matching 
                                      !     variants)

See Also