Intel® Fortran Compiler 16.0 User and Reference Guide
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 |
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:
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:
Variables that have the POINTER attribute
Cray* pointers
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
…
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)