scan Directive
10.10. scan Directive#
The following examples illustrate how to parallelize a loop that saves the prefix sum of a reduction. This is accomplished by using the inscan modifier in the reduction clause for the input variable of the scan, and specifying with a scan directive whether the storage statement includes or excludes the scan input of the present iteration ( k ).
Basically, the inscan modifier connects a loop and/or SIMD reduction to the scan operation, and a scan construct with an inclusive or exclusive clause specifies whether the “scan phase’’ (lexical block before and after the directive, respectively) is to use an inclusive or exclusive scan value for the list item ( x ).
The first example uses the inclusive scan operation on a composite loop-SIMD construct. The scan directive separates the reduction statement on variable x from the use of x (saving to array b ). The order of the statements in this example indicates that value a[k] ( a(k) in Fortran) is included in the computation of the prefix sum b[k] ( b(k) in Fortran) for iteration k .
//%compiler: clang
//%cflags: -fopenmp
/*
* name: scan.1
* type: C
* version: omp_5.0
*/
#include <stdio.h>
#define N 100
int main(void)
{
int a[N], b[N];
int x = 0;
// initialization
for (int k = 0; k < N; k++)
a[k] = k + 1;
// a[k] is included in the computation of producing results in b[k]
#pragma omp parallel for simd reduction(inscan,+: x)
for (int k = 0; k < N; k++) {
x += a[k];
#pragma omp scan inclusive(x)
b[k] = x;
}
printf("x = %d, b[0:3] = %d %d %d\n", x, b[0], b[1], b[2]);
// 5050, 1 3 6
return 0;
}
!!%compiler: gfortran
!!%cflags: -fopenmp
! name: scan.1
! type: F-free
! version: omp_5.0
program inclusive_scan
implicit none
integer, parameter :: n = 100
integer a(n), b(n)
integer x, k
! initialization
x = 0
do k = 1, n
a(k) = k
end do
! a(k) is included in the computation of producing results in b(k)
!$omp parallel do simd reduction(inscan,+: x)
do k = 1, n
x = x + a(k)
!$omp scan inclusive(x)
b(k) = x
end do
print *,'x =', x, ', b(1:3) =', b(1:3)
! 5050, 1 3 6
end program
The second example uses the exclusive scan operation on a composite loop-SIMD construct. The scan directive separates the use of x (saving to array b ) from the reduction statement on variable x . The order of the statements in this example indicates that value a[k] ( a(k) in Fortran) is excluded from the computation of the prefix sum b[k] ( b(k) in Fortran) for iteration k .
//%compiler: clang
//%cflags: -fopenmp
/*
* name: scan.2
* type: C
* version: omp_5.0
*/
#include <stdio.h>
#define N 100
int main(void)
{
int a[N], b[N];
int x = 0;
// initialization
for (int k = 0; k < N; k++)
a[k] = k + 1;
// a[k] is not included in the computation of producing
// results in b[k]
#pragma omp parallel for simd reduction(inscan,+: x)
for (int k = 0; k < N; k++) {
b[k] = x;
#pragma omp scan exclusive(x)
x += a[k];
}
printf("x = %d, b[0:3] = %d %d %d\n", x, b[0], b[1], b[2]);
// 5050, 0 1 3
return 0;
}
!!%compiler: gfortran
!!%cflags: -fopenmp
! name: scan.2
! type: F-free
! version: omp_5.0
program exclusive_scan
implicit none
integer, parameter :: n = 100
integer a(n), b(n)
integer x, k
! initialization
x = 0
do k = 1, n
a(k) = k
end do
! a(k) is not included in the computation of producing results in b(k)
!$omp parallel do simd reduction(inscan,+: x)
do k = 1, n
b(k) = x
!$omp scan exclusive(x)
x = x + a(k)
end do
print *,'x =', x, ', b(1:3) =', b(1:3)
! 5050, 0 1 3
end program