diff --git a/source/elements/oneDPL/source/parallel_api.rst b/source/elements/oneDPL/source/parallel_api.rst index 19769e0d37..c0945c9fba 100644 --- a/source/elements/oneDPL/source/parallel_api.rst +++ b/source/elements/oneDPL/source/parallel_api.rst @@ -1,4 +1,5 @@ .. SPDX-FileCopyrightText: 2019-2022 Intel Corporation +.. SPDX-FileCopyrightText: Contributors to the oneAPI Specification project. .. .. SPDX-License-Identifier: CC-BY-4.0 @@ -10,6 +11,9 @@ including parallel algorithms added in the 6th edition known as C++20. All those algorithms work with *C++ Standard aligned execution policies* and with *device execution policies*. +oneDPL also provides *parallel range algorithms*: variations of C++20 range-based algorithms +that take a oneDPL execution policy. + Additionally, oneDPL provides wrapper functions for `SYCL`_ buffers, special iterators, and a set of non-standard parallel algorithms. @@ -20,6 +24,7 @@ a set of non-standard parallel algorithms. parallel_api/buffer_wrappers.rst parallel_api/iterators.rst parallel_api/algorithms.rst - + parallel_api/parallel_range_api.rst + .. _`C++ Standard`: https://isocpp.org/std/the-standard .. _`SYCL`: https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html diff --git a/source/elements/oneDPL/source/parallel_api/parallel_range_api.rst b/source/elements/oneDPL/source/parallel_api/parallel_range_api.rst new file mode 100644 index 0000000000..ff3f348349 --- /dev/null +++ b/source/elements/oneDPL/source/parallel_api/parallel_range_api.rst @@ -0,0 +1,327 @@ +.. SPDX-FileCopyrightText: Contributors to the oneAPI Specification project. +.. +.. SPDX-License-Identifier: CC-BY-4.0 + +Parallel Range Algorithms +------------------------- + +oneDPL provides variations of algorithms that work with ranges defined in the `C++ Standard`_, 6th edition (C++20) +and newer. These algorithms execute according to a oneDPL execution policy supplied as the first argument, +similarly to other oneDPL algorithms. + +The oneDPL parallel range algorithms rely on the functionality of C++20 and are not available in the code +compiled for earlier editions of the C++ standard. + +The parallel range algorithms reside in ``namespace oneapi::dpl::ranges``. Same as the range algorithm functions +defined by the C++ standard in ``namespace std::ranges``, they cannot be found by argument-dependent name lookup +and cannot be called with explicitly specified template arguments. [*Note*: A typical implementation uses +predefined function objects which static function call operators have the required signatures. -- *end note*] + +The following differences to the standard C++ range algorithms apply: + +- Parallel range algorithms cannot be used in constant expressions. +- The execution policy parameter is added. +- Output data sequences are defined as ranges, not iterators. +- Both input and output ranges must support random access. +- For a given algorithm, at least one of the input ranges as well as the output range must be bounded. +- ``for_each`` does not return its function object. + +Except for these differences, the signatures of parallel range algorithms correspond to the working draft +of the next edition of the C++ standard (C++26). + +Whole Sequence Operations ++++++++++++++++++++++++++ + +.. code:: cpp + + // Defined in + + namespace oneapi::dpl::ranges { + + // all_of + template , Proj> > Pred> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + bool all_of (ExecutionPolicy&& pol, R&& r, Pred pred, Proj proj = {}); + + // any_of + template , Proj> > Pred> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + bool any_of (ExecutionPolicy&& pol, R&& r, Pred pred, Proj proj = {}); + + // none_of + template , Proj> > Pred> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + bool none_of (ExecutionPolicy&& pol, R&& r, Pred pred, Proj proj = {}); + + // for_each + template , Proj> > Fn> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + std::ranges::borrowed_iterator_t + for_each (ExecutionPolicy&& pol, R&& r, Fn f, Proj proj = {}); + + // count + template , Proj>> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && + std::indirect_binary_predicate< std::ranges::equal_to, + std::projected, Proj>, + const T* > + std::ranges::range_difference_t + count (ExecutionPolicy&& pol, R&& r, const T& value, Proj proj = {}); + + // count_if + template , Proj> > Pred> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + std::ranges::range_difference_t + count_if (ExecutionPolicy&& pol, R&& r, Pred pred, Proj proj = {}); + + } + +Element Search Operations ++++++++++++++++++++++++++ + +.. code:: cpp + + // Defined in + + namespace oneapi::dpl::ranges { + + // find + template , Proj>> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && + std::indirect_binary_predicate< std::ranges::equal_to, + std::projected, Proj>, + const T* > + std::ranges::borrowed_iterator_t + find (ExecutionPolicy&& pol, R&& r, const T& value, Proj proj = {}); + + // find_if + template , Proj> > Pred> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + std::ranges::borrowed_iterator_t + find_if (ExecutionPolicy&& pol, R&& r, Pred pred, Proj proj = {}); + + // find_if_not + template , Proj> > Pred> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + std::ranges::borrowed_iterator_t + find_if_not (ExecutionPolicy&& pol, R&& r, Pred pred, Proj proj = {}); + + // adjacent_find + template , Proj>, + std::projected, Proj> > + Pred = std::ranges::equal_to> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + std::ranges::borrowed_iterator_t + adjacent_find (ExecutionPolicy&& pol, R&& r, Pred pred = {}, Proj proj = {}); + + // min_element + template , Proj> > + Comp = std::ranges::less> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + std::ranges::borrowed_iterator_t + min_element (ExecutionPolicy&& pol, R&& r, Comp comp = {}, Proj proj = {}); + + // max_element + template , Proj> > + Comp = std::ranges::less> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + std::ranges::borrowed_iterator_t + max_element (ExecutionPolicy&& pol, R&& r, Comp comp = {}, Proj proj = {}); + + } + +Sequence Search and Comparison +++++++++++++++++++++++++++++++ + +.. code:: cpp + + // Defined in + + namespace oneapi::dpl::ranges { + + // equal + template + requires oneapi::dpl::is_execution_policy_v> && + (std::ranges::sized_range || std::ranges::sized_range) && + std::indirectly_comparable< std::ranges::iterator_t, std::ranges::iterator_t, + Pred, Proj1, Proj2 > + bool equal (ExecutionPolicy&& pol, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); + + // search + template + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && std::ranges::sized_range && + std::indirectly_comparable< std::ranges::iterator_t, std::ranges::iterator_t, + Pred, Proj1, Proj2 > + std::ranges::borrowed_subrange_t + search (ExecutionPolicy&& pol, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); + + // search_n + template, Proj>> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && + std::indirectly_comparable< std::ranges::iterator_t, const T*, Pred, Proj > + std::ranges::borrowed_subrange_t + search_n (ExecutionPolicy&& pol, R&& r, std::ranges::range_difference_t count, + const T& value, Pred pred = {}, Proj proj = {}); + + } + +Sorting and Merge ++++++++++++++++++ + +.. code:: cpp + + // Defined in + + namespace oneapi::dpl::ranges { + + // sort + template + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && std::sortable, Comp, Proj> + std::ranges::borrowed_iterator_t + sort (ExecutionPolicy&& pol, R&& r, Comp comp = {}, Proj proj = {}); + + // stable_sort + template + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && std::sortable, Comp, Proj> + std::ranges::borrowed_iterator_t + stable_sort (ExecutionPolicy&& pol, R&& r, Comp comp = {}, Proj proj = {}); + + // is_sorted + template , Proj> > + Comp = std::ranges::less> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range + bool is_sorted (ExecutionPolicy&& pol, R&& r, Comp comp = {}, Proj proj = {}); + + // merge + template + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && std::ranges::sized_range && + std::ranges::sized_range && + std::mergeable, std::ranges::iterator_t, + std::ranges::iterator_t, Comp, Proj1, Proj2> + std::ranges::merge_result, + std::ranges::borrowed_iterator_t, + std::ranges::borrowed_iterator_t> + merge (R1&& r1, R2&& r2, OutR&& result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + } + +Mutating Operations ++++++++++++++++++++ + +.. code:: cpp + + // Defined in + + namespace oneapi::dpl::ranges { + + // copy + template + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && std::ranges::sized_range && + std::indirectly_copyable, std::ranges::iterator_t> + std::ranges::copy_result, + std::ranges::borrowed_iterator_t> + copy (ExecutionPolicy&& pol, R&& r, OutR&& result); + + // copy_if + template , Proj> > Pred> + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && std::ranges::sized_range && + std::indirectly_copyable, std::ranges::iterator_t> + std::ranges::copy_if_result, + std::ranges::borrowed_iterator_t> + copy_if (ExecutionPolicy&& pol, R&& r, OutR&& result, Pred pred, Proj proj = {}); + + // transform (unary) + template + requires oneapi::dpl::is_execution_policy_v> && + std::ranges::sized_range && std::ranges::sized_range && + std::indirectly_writable< std::ranges::iterator_t, + std::indirect_result_t, Proj>> > + std::ranges::unary_transform_result, + std::ranges::borrowed_iterator_t> + transform (ExecutionPolicy&& pol, R&& r, OutR&& result, Fn unary_op, Proj proj = {}); + + // transform (binary) + template + requires oneapi::dpl::is_execution_policy_v> && + (std::ranges::sized_range || std::ranges::sized_range) && + std::ranges::sized_range && + std::indirectly_writable< std::ranges::iterator_t, + std::indirect_result_t, Proj1>, + std::projected, Proj2>> > + std::ranges::binary_transform_result, + std::ranges::borrowed_iterator_t, + std::ranges::borrowed_iterator_t> + transform (ExecutionPolicy&& pol, R1&& r1, R2&& r2, OutR&& result, Fn binary_op, + Proj1 proj1 = {}, Proj2 proj2 = {}); + + } + +.. _`C++ Standard`: https://isocpp.org/std/the-standard +.. _`SYCL`: https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html