OpenMP* Fortran Compiler Directive: Identifies a variant of a base procedure and specifies the context in which this variant is used. This feature is only available for ifx.
!$OMP DECLARE VARIANT ([base-proc-name:]variant-proc-name) match (context-selector-specification)
base-proc-name |
Is the name of a base procedure. It is the name that appears in a procedure reference and is replaced by the variant name if the procedure reference appears in the OpenMP* context specified by the match clause. |
variant-proc-name |
Is the name of the variant procedure that is to be called instead of the base procedure if the base procedure is called from an OpenMP* context that matches the context specified by the match clause. |
context-selector-specification |
Is construct = {target variant dispatch}, device = {arch (gen)}. Note: currently ifx only allows this context-selector-specification and not others permitted by the OpenMP* specification. The general capability will be allowed in a subsequent release. |
The DECLARE VARIANT directive is a declarative directive and must appear in the specification part of a subroutine or function, or in an interface in an interface block. It identifies the name of a variant procedure that is to be called instead of the base procedure when the call appears in a context that matches the context-selector-specification in the match clause.
If base-proc-name is not specified, the name of the procedure containing the directive is the base-proc-name. base-proc-name must not be a generic name, a procedure pointer, or an alternate entry name.
If a DECLARE VARIANT directive appears in an interface body for a procedure, it must match a DECLARE VARIANT directive in the definition of that procedure. If a DECLARE VARIANT directive appears for a procedure with an explicit interface, and the definition of that procedure also contains a DECLARE VARIANT directive for that procedure, the two directives must match.
Multiple DECLARE VARIANT directives can associate different variant-proc-names with the same base-proc-name. If more than one DECLARE VARIANT associates the same variant-proc-name with the same base-proc-name, then the context-selector-specification must be the same for all such directives.
A variant function must have the same interface characteristics as the base function, except that a variant function must have one additional argument final argument declared in its dummy argument list, which must be of type C_PTR from the intrinsic module ISO_C_BINDING. When a call to the base procedure is replaced by a call to the variant, the compiler adds the additional argument into the actual argument list.
Calling a function variant directly by variant-proc-name within an OpenMP* context that is different than the context specified in the match clause is non-conforming.
The DECLARE VARIANT directive in the module procedure vecadd_base identifies the procedure vecadd_gpu_offload as a variant that is to replace references to vecadd_base when called from a TARGET DISPATCH VARIANT construct and a GEN device is available for offloading. Notice that vecadd_base does not have any dummy arguments, while vecadd_gpu_offload has a single C_PTR dummy argument.
MODULE vecadd
INTEGER,PARAMETER :: n = 1024
CONTAINS
FUNCTION vecadd_gpu_offload (ptr) RESULT (res)
USE,INTRINSIC :: ISO_C_BINDING, ONLY : c_ptr
!$DEC ATTRIBUTES NOINLINE :: vecadd_gpu_offload
TYPE (c_ptr) :: ptr
REAL :: res
REAL,DIMENSION(n) :: a, b
INTEGER :: k
!$omp TARGET PARALLEL DO REDUCTION (+: res) MAP(TO: a, b)
DO k= 0, n - 1
a(k) = k
b(k) = k + 1
res = a(k) + b(k)
END DO
!$omp END TARGET PARALLEL DO
PRINT *, "GPU version of vecadd called"
END FUNCTION vecadd_gpu_offload
FUNCTION vecadd_base ()RESULT (res)
!$DEC ATTRIBUTES NOINLINE :: vecadd_base
!$OMP DECLARE VARIANT (vecadd_gpu_offload) match(construct={target variant dispatch}&
!$OMP& ,device = {arch (gen)} )
REAL :: res
REAL,DIMENSION(n) :: a, b
INTEGER :: k
!$omp PARALLEL DO REDUCTION (+: res)
DO k = 1, n
a(k) = k
a(k) = k + 1
res = a(k) + b(k)
END DO
!$omp END PARALLEL DO
PRINT *, "CPU version of vecadd called"
END FUNCTION vecadd_base
END MODULE vecadd
PROGRAM main
USE vecadd
REAL :: result = 0.0
!$OMP TARGET VARIANT DISPATCH
result = vecadd_base ()
!$OMP END TARGET VARIANT DISPATCH
IF (result == 1048576.0) then
PRINT *, "PASSED: correct results"
ELSE
PRINT *, "FAILED: incorrect results"
ENDIF
END PROGRAM