DECLARE VARIANT

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.

Syntax

!$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 (arch-id-list)}, where arch-id-list is a comma-separated list of one or more of the implementation-defined values gen, gen9, XeLP ,XeHP, or x86_64.

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.

Example

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

See Also