4.2. Task Affinity#

The next example illustrates the use of the affinity clause with a task construct. The variables in the affinity clause provide a hint to the runtime that the task should execute “close” to the physical storage location of the variables. For example, on a two-socket platform with a local memory component close to each processor socket, the runtime will attempt to schedule the task execution on the socket where the storage is located.

Because the C/C++ code employs a pointer, an array section is used in the affinity clause. Fortran code can use an array reference to specify the storage, as shown here.

Note, in the second task of the C/C++ code the B pointer is declared shared. Otherwise, by default, it would be firstprivate since it is a local variable, and would probably be saved for the second task before being assigned a storage address by the first task. Also, one might think it reasonable to use the affinity clause affinity(B[:N]) on the second task construct. However, the storage behind B is created in the first task, and the array section reference may not be valid when the second task is generated. The use of the A array is sufficient for this case, because one would expect the storage for A and B would be physically “close” (as provided by the hint in the first task).

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

/*
* name: affinity.6
* type: C
* version: omp_5.0
*/
double * alloc_init_B(double *A, int N);
void     compute_on_B(double *B, int N);

void task_affinity(double *A, int N)
{
   double * B;
   #pragma omp task depend(out:B) shared(B) affinity(A[0:N])
   {
     B = alloc_init_B(A,N);
   }

   #pragma omp task depend( in:B) shared(B) affinity(A[0:N])
   {
     compute_on_B(B,N);
   }

   #pragma omp taskwait
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name:       affinity.6
! type:       F-free
! version: omp_5.0
subroutine task_affinity(A, N)

  external alloc_init_B
  external compute_on_B
  double precision, allocatable :: B(:)

   !$omp task depend(out:B) shared(B) affinity(A)
     call alloc_init_B(B,A)
   !$omp end task

   !$omp task depend(in:B) shared(B) affinity(A)
     call compute_on_B(B)
   !$omp end task

   !$omp taskwait

end subroutine