Range-Based API Algorithms
C++20 introduces the Ranges library. C++20 standard splits ranges into two categories: factories and adaptors. A range factory does not have underlying data. An element is generated on success by an index or by dereferencing an iterator. A range adaptor, from the Intel® oneAPI DPC++ Library (oneDPL) perspective, is a utility that transforms the base range, or another adapted range, into a view with custom behavior.
oneDPL supports an iota_view range factory.
A sycl::buffer wrapped with all_view can be used as the range.
oneDPL considers the supported factories and all_view as base ranges. The range adaptors may be combined into a pipeline with a base range at the beginning. For example:
sycl::buffer<int> buf(data, sycl::range<1>(10)); auto range_1 = iota_view(0, 10) | views::reverse(); auto range_2 = all_view(buf) | views::reverse();
For the range, based on the all_view factory, data access is permitted on a device only. size() and empty() methods are allowed to be called on both host and device.
The following algorithms are available to use with the ranges:
- adjacent_find 
- all_of 
- any_of 
- copy 
- copy_if 
- count 
- count_if 
- equal 
- exclusive_scan 
- find 
- find_if 
- find_if_not 
- find_end 
- find_first_of 
- for_each 
- inclusive_scan 
- is_sorted 
- is_sorted_until 
- min_element 
- max_element 
- merge 
- minmax_element 
- move 
- none_of 
- reduce 
- reduce_by_segment 
- remove 
- remove_if 
- remove_copy 
- remove_copy_if 
- replace 
- replace_if 
- replace_copy 
- replace_copy_if 
- reverse 
- reverse_copy 
- rotate_copy 
- search 
- sort 
- stable_sort 
- swap_ranges 
- transform 
- transform_reduce 
- transform_exclusive_scan 
- transform_inclusive_scan 
- unique 
- unique_copy 
The signature example of the range-based algorithms looks like:
template <typename ExecutionPolicy, typename Range1, typename Range2> void copy(ExecutionPolicy&& exec, Range1&& source, Range2&& destination);
where source is used instead of two iterators to represent the input, and destination represents the output.
These algorithms are declared in the oneapi::dpl::experimental::ranges namespace and implemented only for device execution policies. To make these algorithms available, the <oneapi/dpl/ranges> header should be included (after <oneapi/dpl/execution>). Use of the range-based API requires C++17 and the C++ standard libraries that come with GCC 8.1 (or higher) or Clang 7 (or higher).
The following viewable ranges are declared in the oneapi::dpl::experimental::ranges namespace. Only the ranges shown below and sycl::buffer are available as ranges for range-based algorithms.
- views::iota: A range factory that generates a sequence of N elements, which starts from an initial value and ends by final N-1. 
- views::all: A custom utility that represents a view of all or a part of sycl::buffer underlying elements for reading and writing on a device. 
- views::all_read: A custom utility that represents a view of all or a part of sycl::buffer underlying elements for reading on a device. 
- views::all_write: A custom utility that represents a view of all or a part of sycl::buffer underlying elements for writing on a device. 
- views::host_all: A custom utility that represents a view of all or a part of sycl::buffer underlying elements for reading and writing on the host. 
- views::subrange: A utility that represents a view of unified shared memory (USM) data range defined by a two USM pointers. 
- views::zip: A custom range adapter that produces one zip_view from other several views. 
- views::transform: A range adapter that represents a view of a underlying sequence after applying a transformation to each element. 
- views::reverse: A range adapter that produces a reversed sequence of elements provided by another view. 
- views::take: A range adapter that produces a view of the first N elements from another view. 
- views::drop: A range adapter that produces a view excluding the first N elements from another view. 
Example of Range-Based API Usage
using namespace oneapi::dpl::experimental::ranges;
{
    sycl::buffer<int> A(data, sycl::range<1>(max_n));
    sycl::buffer<int> B(data2, sycl::range<1>(max_n));
    auto view = all_view(A) | views::reverse();
    auto range_res = all_view<int, sycl::access::mode::write>(B);
    copy(oneapi::dpl::execution::dpcpp_default, view, range_res);
}