Experimental Range-Based API#
The <oneapi/dpl/ranges> header file contains experimental classes and functions that implement
the functionality similar to what is provided by the C++20 Ranges Library, yet only requires C++17.
This allows you to combine oneDPL data parallel execution capabilities with some aspects
of modern range-based API. The functionality is only implemented for the device execution policies.
Note
The use of the experimental range-based API requires the C++ standard libraries coming with GCC 8.1 (or higher) or Clang 7 (or higher).
Warning
This experimental functionality will be gradually substituted by the parallel range algorithms and eventually discontinued.
Range Views#
The following viewable ranges are defined in the oneapi::dpl::experimental::ranges namespace:
views::iota: A range factory that generates a sequence of elements by repeatedly incrementing an initial value.views::all: A custom utility that represents a view of all or a part ofsycl::bufferelements for reading and writing on a device.views::all_read: A custom utility that represents a view of all or a part ofsycl::bufferelements for reading on a device.views::all_write: A custom utility that represents a view of all or a part ofsycl::bufferelements for writing on a device.views::host_all: A custom utility that represents a view of all or a part ofsycl::bufferelements for reading and writing on the host.views::subrange: A utility that represents a view of unified shared memory (USM) data range defined by two USM pointers.views::zip: A custom range adaptor that produces onezip_viewfrom other several views.views::transform: A range adaptor that represents a view of an underlying sequence after applying a transformation to each element.views::reverse: A range adaptor that produces a reversed sequence of elements provided by another view.views::take: A range adaptor that produces a view of the first N elements from another view.views::drop: A range adaptor that produces a view excluding the first N elements from another view.
Only these ranges, sycl::buffer, and their combinations can be passed to the experimental range-based algorithms.
A sycl::buffer wrapped with views::all and similar utilities, views::subrange over USM, and views::iota
are considered 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 = views::iota(0, 10) | views::reverse;
auto range_2 = views::all(buf) | views::take(10);
For ranges based on a SYCL buffer, data access is only permitted on a device, while size() and empty()
methods are allowed to be called on both host and device.
Range-Based Algorithms#
The functions for experimental range based algorithms resemble the standard C++ parallel algorithm overloads where all data sequences represented by ranges instead of iterators or iterator pairs, for example:
template <typename ExecutionPolicy, typename Range1, typename Range2>
void copy(ExecutionPolicy&& exec, Range1&& source, Range2&& destination);
Note that source is used instead of two iterators to represent the input, and destination represents the output.
The following algorithms are available to use with the ranges. These algorithms are defined in the
oneapi::dpl::experimental::ranges namespace and can only be invoked with device execution policies.
To use these algorithms, include both <oneapi/dpl/ranges> and <oneapi/dpl/execution> header files.
adjacent_findall_ofany_ofcopycopy_ifcountcount_ifequalexclusive_scanfindfind_iffind_if_notfind_endfind_first_offor_eachinclusive_scanis_sortedis_sorted_untilmin_elementmax_elementmergeminmax_elementmovenone_ofreducereduce_by_segmentremoveremove_ifremove_copyremove_copy_ifreplacereplace_ifreplace_copyreplace_copy_ifreversereverse_copyrotate_copysearchsortstable_sortswap_rangestransformtransform_reducetransform_exclusive_scantransform_inclusive_scanuniqueunique_copy
Usage Example#
namespace rangexp = 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 = rangexp::views::all(A) | rangexp::views::reverse;
auto range_res = rangexp::views::all_write(B);
rangexp::copy(oneapi::dpl::execution::dpcpp_default, view, range_res);
}