12.5. requires Directive#

The declarative requires directive can be used to specify features that an implementation must provide to compile and execute correctly.

In the following example the unified_shared_memory clause of the requires directive ensures that the host and all devices accessible through OpenMP provide a unified address space for memory that is shared by all devices.

The example illustrates the use of the requires directive specifying unified shared memory in file scope, before any device directives or device routines. No map clause is needed for the p structure on the device (and its address &p , for the C++ code, is the same address on the host and device). However, scalar variables referenced within the target construct still have a default data-sharing attribute of firstprivate. The q scalar is incremented on the device, and its change is not updated on the host.

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

/*
* name:       requires.1
* type:       C++
* version:    omp_5.0
*/

#include <iostream>
using namespace std;

#pragma omp requires unified_shared_memory

typedef struct mypoints
{
   double res;
   double data[500];
} mypoints_t;

void do_something_with_p(mypoints_t *p, int q);

int main()
{
  mypoints_t p;
  int q=0;

  #pragma omp target // no map clauses needed
  {                  // q is firstprivate
     q++;
     do_something_with_p(&p,q);
  }
  cout<< p.res << " " << q << endl;  // output 1 0
  return 0;
}
void do_something_with_p(mypoints_t *p, int q)
{
  p->res = q;
  for(int i=0;i<sizeof(p->data)/sizeof(double);i++)
      p->data[i]=q*i;
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name:       requires.1
! type:       F-free
! version:    omp_5.0

module data
!$omp requires unified_shared_memory
  type,public :: mypoints
     double precision :: res
     double precision :: data(500)
  end type
end module

program main
  use data
  type(mypoints) :: p
  integer        :: q=0

  !$omp target    !! no map clauses needed
     q = q + 1    !! q is firstprivate
     call do_something_with_p(p,q)
  !$omp end target

  write(*,'(f5.0,i5)') p%res, q    !! output 1.   0

end program

subroutine do_something_with_p(p,q)
  use data
  type(mypoints) :: p
  integer        :: q

  p%res = q;
  do i=1,size(p%data)
     p%data(i)=q*i
  enddo

end subroutine