Scan Operations¶
RAJA provides portable parallel scan operations, which are basic parallel algorithm building blocks. They are described in this section.
A few important notes:
Note
All RAJA scan operations are in the namespace
RAJA
.Each RAJA scan operation is a template on an execution policy parameter. The same policy types used for
RAJA::forall
methods may be used for RAJA scans. Please see Policies for more information.RAJA scan operations accept an optional operator argument so users can perform different types of scan operations. If no operator is given, the default is a ‘plus’ operation and the result is a prefix-sum.
Also:
Note
For scans using the CUDA or HIP back-end, RAJA implementation uses
the NVIDIA CUB library or AMD rocPRIM library, respectively.
Typically, the CMake variable CUB_DIR
or ROCPRIM_DIR
will
be automatically set to the location of the CUB or rocPRIM library
for the CUDA or rocPRIM installation specified when either back-end
is enabled. More details for configuring the CUB or rocPRIM library
for a RAJA build can be found in Dependencies.
Please see the following tutorial sections for detailed examples that use RAJA scan operations:
Scan Operations¶
In general, a scan operation takes a sequence of numbers ‘x’ and a binary associative operator ‘op’ as input and produces another sequence of numbers ‘y’ as output. Each element of the output sequence is formed by applying the operator to a subset of the input. Scans come in two flavors: inclusive and exclusive.
An inclusive scan takes the input sequence
x = { x0, x1, x2, … }
and calculates the output sequence:
y = { y0, y1, y2, … }
using the recursive definition
y0= x0
yi= yi-1op xi, for each i > 0
An exclusive scan is similar, but the output of an exclusive scan is different from the output of an inclusive scan in two ways. First, the first element of the output is the identity of the operator used. Second, the rest of the output sequence is the same as inclusive scan, but shifted one position to the right; i.e.,
y0= opidentity
yi= yi-1 op xi-1, for each i > 0
If you would like more information about scan operations, a good overview of what they are and why they are useful can be found in Blelloch Scan Lecture Notes. A nice presentation that describes how parallel scans are implemented is Va Tech Scan Lecture
RAJA Inclusive Scans¶
RAJA inclusive scan operations look like the following:
RAJA::inclusive_scan< exec_policy >(in_container, out_container)
RAJA::inclusive_scan< exec_policy >(in_container, out_container, operator)
Here, ‘in_container’ and ‘out_container’ are random access ranges of some
numeric scalar type whose elements are the input and output sequences of the
scan, respectively. The scalar type must be the same for both arrays. The first
scan operation above will be a prefix-sum since there is no operator argument
given; i.e., the output array will contain partial sums of the input array. The
second scan will apply the operator that is passed. Note that container
arguments can be generated from iterators using RAJA::make_span(begin, len)
.
This is shown in the examples in Parallel Scan Operations.
RAJA also provides in-place scans:
RAJA::inclusive_scan_inplace< exec_policy >(in_container)
RAJA::inclusive_scan_inplace< exec_policy >(in_container, operator)
An in-place scan generates the same output sequence as a non-inplace scan. However, an in-place scan does not take separate input and output arrays and the result of the scan operation will appear in-place in the input array.
RAJA Exclusive Scans¶
Using RAJA exclusive scans is essentially the same as for inclusive scans:
RAJA::exclusive_scan< exec_policy >(in_container, out_container)
RAJA::exclusive_scan< exec_policy >(in_container, out_container, operator)
and
RAJA::exclusive_scan_inplace< exec_policy >(in_container)
RAJA::exclusive_scan_inplace< exec_policy >(in_container, <operator>)
RAJA Scan Operators¶
RAJA provides a variety of operators that can be used to perform different types of scans, such as:
RAJA::operators::plus<T>
RAJA::operators::minus<T>
RAJA::operators::multiplies<T>
RAJA::operators::divides<T>
RAJA::operators::minimum<T>
RAJA::operators::maximum<T>
Note
All RAJA scan operators are in the namespace
RAJA::operators
.