6.2. defaultmap Clause#

The implicitly-determined, data-mapping and data-sharing attribute rules of variables referenced in a target construct can be changed by the defaultmap clause introduced in OpenMP 5.0. The implicit behavior is specified as alloc, to, from, tofrom, firstprivate, none, default or present, and is applied to a variable-category, where scalar, aggregate, allocatable, and pointer are the variable categories.

In OpenMP, a “category’’ has a common data-mapping and data-sharing behavior for variable types within the category. In C/C++, scalar refers to base-language scalar variables, except pointers. In Fortran it refers to a scalar variable, as defined by the base language, with intrinsic type, and excludes character type.

Also, aggregate refers to arrays and structures (C/C++) and derived types (Fortran). Fortran has the additional category of allocatable.

In the example below, the first target construct uses defaultmap clauses to set data-mapping and possibly data-sharing attributes that reproduce the default implicit mapping (data-mapping and data-sharing attributes). That is, if the defaultmap clauses were removed, the results would be identical.

In the second target construct all implicit behavior is removed by specifying the none implicit behavior in the defaultmap clause. Hence, all variables must be explicitly mapped. In the C/C++ code a scalar ( s ), an array ( A ) and a structure ( S ) are explicitly mapped tofrom. The Fortran code uses a derived type ( D ) in lieu of structure.

The third target construct shows another usual case for using the defaultmap clause. The default mapping for (non-pointer) scalar variables is specified as tofrom. Here, the default implicit mapping for s3 is tofrom as specified in the defaultmap clause, and s1 and s2 are explicitly mapped with the firstprivate data-sharing attribute.

In the fourth target construct all arrays, structures (C/C++) and derived types (Fortran) are mapped with firstprivate data-sharing behavior by a defaultmap clause with an aggregate variable category. For the H allocated array in the Fortran code, the allocable category must be used in a separate defaultmap clause to acquire firsprivate data-sharing behavior ( H has the Fortran allocatable attribute).

//%compiler: clang
//%cflags: -fopenmp

/*
* name:       target_defaultmap.1
* type:       C
* version: omp_5.0
*/
#include <stdlib.h>
#include <stdio.h>
#define N 2

int main(){
  typedef struct S_struct { int s; int A[N]; } S_struct_t;


  int         s;       //scalar int variable (scalar)
  int         A[N];    //aggregate variable  (array)
  S_struct_t  S;       //aggregate variable  (structure)
  int         *ptr;    //scalar, pointer variable (pointer)

  int         s1, s2, s3;

// Initialize everything to zero;
   s=2; s1=s2=s3=0;
   A[0]=0; A[1]=0;
   S.s=0; S.A[0]=0; S.A[1]=0;

// Target Region 1
                   // Uses defaultmap to set scalars, aggregates &
                   // pointers to normal defaults.
    #pragma omp target \
            defaultmap(firstprivate: scalar)   //could also be default \
            defaultmap(tofrom:       aggregate)//could also be default \
            defaultmap(default:      pointer)  //must be default       \
            map(ptr2m[:N])
    {
        s       = 3;            //SCALAR firstprivate, value not returned

        A[0]    = 3;  A[1] = 3; //AGGREGATE array, default map tofrom

                                //AGGREGATE structure, default tofrom
        S.s     = 2;
        S.A[0]  = 2;  S.A[1] = 2;

        ptr = &A[0];            //POINTER is private
        ptr[0] = 2;   ptr[1] = 2;

    }
   if(s==2 && A[0]==2 && S.s==2 && S.A[0]==2)
      printf(" PASSED 1 of 4\n");


// Target Region 2
                   // no implicit mapping allowed.
    #pragma omp target defaultmap(none) map(tofrom: s, A, S)
    {
        s     +=5;           // All variables must be explicitly mapped
        A[0]  +=5; A[1]+=5;
        S.s   +=5;
        S.A[0]+=5; S.A[1]+=5;
    }
    if(s==7 && A[0]==7 && S.s==7 && S.A[0]==7)
        printf(" PASSED 2 of 4\n");


// Target Region 3
            // defaultmap & explicit map with variables in same category
    s1=s2=s3=1;
    #pragma  omp defaultmap(tofrom: scalar) map(firstprivate: s1,s2)
    {
        s1 += 5;         // firstprivate (s1 value not returned to host)
        s2 += 5;         // firstprivate (s2 value not returned to host)
        s3 += s1 + s2;   // mapped as tofrom
    }
    if(s1==1 && s2==1 && s3==13 ) printf(" PASSED 3 of 4\n");


// Target Region 4
    A[0]=0; A[1]=0;
    S.A[0]=0; S.A[1]=0;

    // arrays and structure are firstprivate, and scalars are from
    #pragma omp target defaultmap(firstprivate: aggregate) \
                       map(from: s1, s2)
    {

        A[0]+=1; S.A[0]+=1; //Aggregate changes not returned to host
        A[1]+=1; S.A[1]+=1; //Aggregate changes not returned to host
        s1 = A[0]+S.A[0]; //s1 value returned to host
        s2 = A[1]+S.A[1]; //s1 value returned to host
    }
    if( A[0]==0 && S.A[0]==0 && s1==2 ) printf(" PASSED 4 of 4\n");

}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name:       target_defaultmap.1
! type:       F-free
! version:    omp_5.0
program defaultmap
  integer, parameter :: N=2

  type DDT_sA
    integer  :: s
    integer  :: A(N)
  end type

  integer             :: s,s1,s2,s3 !! SCALAR: variable (integer)

  integer,target      :: A(N)       !! AGGREGATE: Array
  type(DDT_sA)        :: D          !! AGGREGATE: Derived Data Type (D)

  integer,allocatable :: H(:)       !! ALLOCATABLE: Heap allocated array

  integer,pointer     :: ptrA(:)    !! POINTER: points to Array

  ! Assign vaues to scalar, Array, Allocatable, and Pointers

    s=2;
    s1=0;   s2=0;     s3=0
    D%s=0;  D%A(1)=0; D%A(2)=0
    A(1)=0; A(2)=0

    allocate( H(2) )
    H(1)=0; H(2)=0

!! Target Region 1
                   !! Using defaultmap to set scalars, aggregates &
                   !! pointers and allocatables to normal defaults.
    !$omp target                                        &
    !$omp&       defaultmap( firstprivate: scalar)      &
    !$omp&       defaultmap( tofrom:       aggregate)   &
    !$omp&       defaultmap( tofrom:       allocatable) &
    !$omp&       defaultmap( default:      pointer)

        s = 3                     !! SCALAR firstprivate, val not returned

        A(1) = 3                  !! AGGREGATE array, default map tofrom
        A(2) = 3

        D%s = 2                   !! AGGR. Derived Type, default map tofrom
        D%A(1) = 2;  D%A(2) = 2

        H(1) = 2;    H(2) = 2     !! ALLOCATABLE, default map tofrom

        ptrA=>A                   !! POINTER is private
        ptrA(1) = 2; ptrA(2) = 2

    !$omp end target

    if(s==2 .and. A(1)==2 .and. D%s==2 .and. D%A(1)==2 .and. H(1) == 2) &
       print*," PASSED 1 of 4"

!! Target Region 2
                   !! no implicit mapping allowed
    !$omp target defaultmap(none) map(tofrom: s, A, D)

        s=s+5                 !! All variables must be explicitly mapped
        A(1)=A(1)+5;       A(2)=A(2)+5
        D%s=D%s+5
        D%A(1)=D%A(1)+5; D%A(2)=D%A(2)+5

    !$omp end target
    if(s==7 .and. A(1)==7 .and. D%s==7 .and. D%A(1)==7) &
        print*," PASSED 2 of 4"

!! Target Region 3
                !!defaultmap & explicit map with variables in same category
    s1=1; s2=1; s3=1
    !$omp defaultmap(tofrom: scalar) map(firstprivate: s1,s2)

        s1 = s1+5;          !! firstprivate (s1 value not returned to host)
        s2 = s2+5;          !! firstprivate (s2 value not returned to host)
        s3 = s3 +s1 + s2;   !! mapped as tofrom

    !$omp end target
    if(s1==1 .and. s2==1 .and. s3==13) print*," PASSED 3 of 4"

!! Target Region 4
    A(1)=0;   A(2)=0
    D%A(1)=0; D%A(2)=0
    H(1)=0;   H(2)=0
              !! non-allocated arrays & derived types are in AGGREGATE cat.
              !! Allocatable Arrays are in ALLOCATABLE category
              !! Scalars are explicitly mapped from
    !$omp target defaultmap(firstprivate: aggregate )  &
    !$omp&       defaultmap(firstprivate: allocatable) &
    !$omp&       map(from: s1, s2)

        A(1)=A(1)+1; D%A(1)=D%A(1)+1; H(1)=H(1)+1 !! changes to A, D%A, H
        A(2)=A(2)+1; D%A(2)=D%A(2)+1; H(2)=H(2)+1 !!   not returned to host
        s1 = A(1)+D%A(1)+H(1)                     !! s1 returned to host
        s2 = A(2)+D%A(2)+H(1)                     !! s2 returned to host

    !$omp end target
    if(A(1)==0 .and. D%A(1)==0 .and. H(1)==0 .and. s1==3) &
       print*," PASSED 4 of 4"

    deallocate(H)

end program