Intel® Fortran Compiler 16.0 User and Reference Guide

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.

It takes one of the following forms:

In Construct Directive !$OMP SIMD:

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

In Declarative Directive !$OMP DECLARE SIMD:

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

var-list

Is a comma-separated list of one or more integer variables. Each list item must comply with PRIVATE clause semantics.

For each iteration of a scalar loop, the value of each var is incremented by linear-step. For each iteration of a vector loop, the value of each var is incremented by linear-step times the vector length for the loop.

linear-step

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

linear-list

Takes one of the following forms:

  • list

  • modifier (list)

list

Is a comma-separated list of one or more dummy arguments of the procedure that will be invoked concurrently on each SIMD lane. Each list item must comply with PRIVATE clause semantics.

If modifier is not specified or it is VAL or UVAL, each list item must be a scalar of type integer. If modifier is REF, each list item must be a scalar of intrinsic type.

modifier

Is one of the following:

  • REF

    Specifies that the storage location of each 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 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 step.

    This modifier can be used only for dummy arguments passed by reference.

  • VAL

    Specifies that the value of each list item on each lane corresponds to the value of the 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 + 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.

If modifier is not specified or it is VAL or UVAL, the value of each list item on each lane corresponds to the value of the 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 list item is a dummy argument without the Fortran Standard VALUE attribute.

If more than one linear-step is specified for a var, a compile-time error occurs. Multiple LINEAR clauses can be used to specify different values for linear-step. 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 corresponding to the sequentially last iteration of the associated loops is assigned to the original list item.

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

In the sequentially last iteration, any list item with the ALLOCATABLE attribute must have an allocation status of allocated upon exit from that iteration.

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

The following cannot appear in a LINEAR clause:

The LINEAR (REF) clause 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 (REF (X)) tells the compiler that the 4 addresses for the dummy argument X are consecutive, so the code only needs to dereference X once and then copy consecutive values to a vector register.

subroutine test_linear(x, y)
!$omp declare simd (test_linear) linear(ref(x, y))    ! arguments by reference
    real(8),intent(in)  :: x
    real(8),intent(out) :: y  
    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(REF(in2)) UNIFORM(mul)  
!    
! matches the use of func in loops 2 and 3:
!$OMP DECLARE SIMD LINEAR(REF(in2)) 
!                   
! matches the use of func in loop 2:
!$OMP DECLARE SIMD LINEAR(REF(in2)) LINEAR(mul)
!        
! matches the use of func in loop 3:
!$OMP DECLARE SIMD LINEAR(VAL(in2:2))                  

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 are 
      c(i) = func(b(ndx(i)), k, b(i)) !     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))) will 
   END DO                             !     be chosen from the two matching variants)

See Also