Skip to content

Commit caabb9e

Browse files
[oneDPL] Improve clarity in buffer wrapper usage (#649)
Signed-off-by: Dan Hoeflinger <[email protected]> Co-authored-by: Alexey Kukanov <[email protected]>
1 parent 7de8761 commit caabb9e

File tree

3 files changed

+39
-15
lines changed

3 files changed

+39
-15
lines changed

source/elements/oneDPL/source/parallel_api/buffer_wrappers.rst

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@
66
Buffer Wrappers
77
---------------
88

9+
A *buffer wrapper* is an iterator-like type for processing data in `SYCL`_ buffers with oneDPL algorithms.
10+
It is either the type of a *buffer position object* returned by
11+
``oneapi::dpl::begin`` or ``oneapi::dpl::end`` or a type composed of at least one buffer position object,
12+
with the same capabilities and limitations as buffer position objects.
13+
Buffer wrappers can be used as source types for :doc:`oneDPL iterators <iterators>`, and the resulting type is also a
14+
buffer wrapper.
15+
16+
Buffer wrappers substitute for iterators as arguments and return values of oneDPL algorithms, however they cannot be
17+
used as iterators in other contexts, including dereference, as these types do not fully satisfy the C++ standard
18+
requirements for an iterator.
19+
20+
Buffer Position Objects
21+
-----------------------
22+
923
.. code:: cpp
1024
1125
// Defined in <oneapi/dpl/iterator>
@@ -48,14 +62,18 @@ which type satisfies the following requirements but is otherwise unspecified:
4862

4963
- It is copy-constructible and copy-assignable.
5064
- It is comparable with ``operator==`` and ``operator!=``.
51-
- It provides the ``get_buffer()`` method that for a buffer position object returns the SYCL buffer,
52-
which the object was built over.
5365
- The expressions ``a + n`` and ``a - n``, where ``a`` is a buffer position object and ``n``
5466
is an integer value, are valid and evaluate to a buffer position object such that
5567
the corresponding position in the buffer follows (precedes) that of ``a`` by ``n``.
5668
If this new position is out of the buffer bounds, the behavior is undefined.
5769
- The expression ``a - b``, where ``a`` and ``b`` are buffer position objects,
5870
is valid and evaluates to an integer value ``n`` such that ``a == b + n``.
71+
- It provides the ``get_buffer()`` method that for a buffer position object returns the SYCL buffer,
72+
which the object was built over.
73+
74+
.. note::
75+
Only buffer position objects are required to support the ``get_buffer()`` method, other buffer wrappers
76+
composed of buffer position objects are not required to support this method.
5977

6078
If these operators and expressions are applied to buffer position objects that are not built
6179
over the same SYCL buffer, the behavior is undefined.
@@ -73,10 +91,6 @@ in expressions with other objects built over the same buffer.
7391
auto pos = dpl::find(dpl::execution::dpcpp_default, dpl::begin(buf), dpl::end(buf), value);
7492
int value_index = (pos == dpl::end(buf)) ? -1 : (pos - dpl::begin(buf));
7593
76-
.. note::
77-
Though buffer position objects substitute for iterators as arguments and return values
78-
of oneDPL algorithms, they cannot be used as iterators in other contexts, including dereference,
79-
as their type does not satisfy the C++ standard requirements for an iterator.
8094
8195
SYCL deduction tags (the ``TagT`` parameters) and ``sycl::property::no_init``
8296
allow to specify an access mode to be used by algorithms for accessing a SYCL buffer.

source/elements/oneDPL/source/parallel_api/execution_policies.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ device_policy Class
9696
9797
An object of the ``device_policy`` type is associated with a ``sycl::queue`` that is used
9898
to run algorithms on a SYCL device. When an algorithm runs with ``device_policy``
99-
it is capable of processing SYCL buffers (passed via ``oneapi::dpl::begin/end``),
100-
data in the host memory and data in Unified Shared Memory (USM), including device USM.
101-
Data placed in the host memory and USM can be passed to oneDPL algorithms
99+
it is capable of processing SYCL buffers (passed via ``oneapi::dpl::begin/end`` or other
100+
:doc:`buffer wrappers <buffer_wrappers>`), data in the host memory and data in Unified Shared Memory (USM), including
101+
device USM. Data placed in the host memory and USM can be passed to oneDPL algorithms
102102
as pointers and random access iterators, including :doc:`oneDPL iterators <iterators>`. The way to transfer data from
103103
the host memory to a device and back is unspecified; per-element data movement to/from a temporary storage is a possible
104104
valid implementation.

source/elements/oneDPL/source/parallel_api/iterators.rst

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ iterators. However, they are indirectly device accessible because they represent
2424
When passed to oneDPL algorithms with a ``device_policy``, indirectly device accessible iterator types that are also
2525
random access iterators and satisfy *SYCL device-copyable* must not cause unnecessary data movement beyond what is
2626
required by the algorithm's semantics and what would be required to use the type directly within a SYCL kernel.
27-
Indirectly device accessible buffer position objects must not cause unnecessary data movement beyond what is
28-
required by the algorithm's semantics and what would be required by using an accessor to the buffer within a SYCL
29-
kernel.
27+
28+
Similarly, when passed to oneDPL algorithms with a ``device_policy``, buffer position objects must not cause
29+
unnecessary data movement beyond what is required by the algorithm's semantics and what would be required
30+
by using an accessor to the buffer within a SYCL kernel.
31+
32+
The same requirement to prevent excessive data movements equally applies to indirectly device accessible types
33+
composed of one or more source components, such as the oneDPL iterators.
3034

3135
Indirect Device Accessibility Type Trait
3236
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,17 +56,20 @@ oneDPL Iterators
5256
The oneDPL iterators are defined in the ``<oneapi/dpl/iterator>`` header,
5357
in ``namespace oneapi::dpl``.
5458

55-
Let us define a named requirement, ``AdaptingIteratorSource``, to describe valid random access iterator-like
59+
Let us define a named requirement, ``AdaptingIteratorSource``, to describe random access iterator-like
5660
types that can be used as source for oneDPL iterators as described below.
5761
The type ``Iter`` satisfies the ``AdaptingIteratorSource`` named requirement if it is any of the following:
5862

5963
* A random access iterator
60-
* The unspecified iterator-like type returned by ``oneapi::dpl::begin`` or ``oneapi::dpl::end``
6164
* A ``permutation_iterator``
6265
* A ``transform_iterator``
6366
* A ``counting_iterator``
6467
* A ``discard_iterator``
6568
* A ``zip_iterator``
69+
* A :doc:`buffer position object <buffer_wrappers>` type returned by ``oneapi::dpl::begin`` and ``oneapi::dpl::end``
70+
71+
If ``AdaptingIteratorSource`` is a buffer wrapper, a type built upon that also becomes a buffer wrapper,
72+
not an iterator, and cannot be directly dereferenced (see :doc:`Buffer wrappers <buffer_wrappers>`).
6673

6774
.. code:: cpp
6875
@@ -209,12 +216,15 @@ algorithm with a ``device_policy``, ``SourceIterator`` must be indirectly device
209216
The type ``IndexMap`` must be one of the following:
210217

211218
* A random access iterator
212-
* The unspecified iterator-like type returned by ``oneapi::dpl::begin`` or ``oneapi::dpl::end``
213219
* A ``permutation_iterator``
214220
* A ``transform_iterator``
215221
* A ``counting_iterator``
216222
* A functor with a signature equivalent to ``T operator()(const T&) const`` where ``T`` is a
217223
``std::iterator_traits<SourceIterator>::difference_type``
224+
* A :doc:`buffer position object <buffer_wrappers>` type returned by ``oneapi::dpl::begin`` and ``oneapi::dpl::end``
225+
226+
If the ``IndexMap`` is a buffer wrapper, the ``permutation_iterator`` built upon that will be a buffer wrapper, not an
227+
iterator, and cannot be directly dereferenced (see :doc:`Buffer wrappers <buffer_wrappers>`).
218228

219229
``permutation_iterator::operator*`` uses the counter value of the instance on which
220230
it is invoked to index into the index map. The corresponding value in the map is then used

0 commit comments

Comments
 (0)