6.12. target update Construct#

6.12.1. Simple target data and target update Constructs#

The following example shows how the target update construct updates variables in a device data environment.

The target data construct maps array sections v1[:N] and v2[:N] (arrays v1 and v2 in the Fortran code) into a device data environment.

The task executing on the host device encounters the first target region and waits for the completion of the region.

After the execution of the first target region, the task executing on the host device then assigns new values to v1[:N] and v2[:N] ( v1 and v2 arrays in Fortran code) in the task’s data environment by calling the function init_again().

The target update construct assigns the new values of v1 and v2 from the task’s data environment to the corresponding mapped array sections in the device data environment of the target data construct.

The task executing on the host device then encounters the second target region and waits for the completion of the region.

The second target region uses the updated values of v1[:N] and v2[:N] .

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

/*
* name: target_update.1
* type: C
* version: omp_4.0
*/
extern void init(float *, float *, int);
extern void init_again(float *, float *, int);
extern void output(float *, int);
void vec_mult(float *p, float *v1, float *v2, int N)
{
   int i;
   init(v1, v2, N);
   #pragma omp target data map(to: v1[:N], v2[:N]) map(from: p[0:N])
   {
      #pragma omp target
      #pragma omp parallel for
      for (i=0; i<N; i++)
 p[i] = v1[i] * v2[i];
      init_again(v1, v2, N);
      #pragma omp target update to(v1[:N], v2[:N])
      #pragma omp target
      #pragma omp parallel for
      for (i=0; i<N; i++)
 p[i] = p[i] + (v1[i] * v2[i]);
   }
   output(p, N);
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: target_update.1
! type: F-free
! version:     omp_4.0
subroutine vec_mult(p, v1, v2, N)
   real    ::  p(N), v1(N), v2(N)
   integer ::  i
   call init(v1, v2, N)
   !$omp target data map(to: v1, v2) map(from: p)
      !$omp target
      !$omp parallel do
         do i=1,N
            p(i) = v1(i) * v2(i)
         end do
      !$omp end target
      call init_again(v1, v2, N)
      !$omp target update to(v1, v2)
      !$omp target
      !$omp parallel do
         do i=1,N
            p(i) = p(i) + v1(i) * v2(i)
         end do
      !$omp end target
   !$omp end target data
   call output(p, N)
end subroutine

6.12.2. target update Construct with if Clause#

The following example shows how the target update construct updates variables in a device data environment.

The target data construct maps array sections v1[:N] and v2[:N] (arrays v1 and v2 in the Fortran code) into a device data environment. In between the two target regions, the task executing on the host device conditionally assigns new values to v1 and v2 in the task’s data environment. The function maybe_init_again() returns true if new data is written.

When the conditional expression (the return value of maybe_init_again()) in the if clause is true , the target update construct assigns the new values of v1 and v2 from the task’s data environment to the corresponding mapped array sections in the target data construct’s device data environment.

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

/*
* name: target_update.2
* type: C
* version: omp_4.0
*/
extern void init(float *, float *, int);
extern int maybe_init_again(float *, int);
extern void output(float *, int);
void vec_mult(float *p, float *v1, float *v2, int N)
{
   int i;
   init(v1, v2, N);
   #pragma omp target data map(to: v1[:N], v2[:N]) map(from: p[0:N])
   {
      int changed;
      #pragma omp target
      #pragma omp parallel for
      for (i=0; i<N; i++)
        p[i] = v1[i] * v2[i];
      changed = maybe_init_again(v1,  N);
      #pragma omp target update if (changed) to(v1[:N])
      changed = maybe_init_again(v2,  N);
      #pragma omp target update if (changed) to(v2[:N])
      #pragma omp target
      #pragma omp parallel for
      for (i=0; i<N; i++)
        p[i] = p[i] + (v1[i] * v2[i]);
   }
   output(p, N);
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: target_update.2
! type: F-free
! version:     omp_4.0
subroutine vec_mult(p, v1, v2, N)
   interface
      logical function maybe_init_again (v1, N)
      real :: v1(N)
      integer :: N
      end function
   end interface
   real    ::  p(N), v1(N), v2(N)
   integer ::  i
   logical :: changed
   call init(v1, v2, N)
   !$omp target data map(to: v1, v2) map(from: p)
      !$omp target
         !$omp parallel do
         do i=1, N
            p(i) = v1(i) * v2(i)
         end do
      !$omp end target
      changed = maybe_init_again(v1, N)
      !$omp target update if(changed) to(v1(:N))
      changed = maybe_init_again(v2, N)
      !$omp target update if(changed) to(v2(:N))
      !$omp target
         !$omp parallel do
         do i=1, N
            p(i) = p(i) + v1(i) * v2(i)
         end do
      !$omp end target
   !$omp end target data
   call output(p, N)
end subroutine