-
Notifications
You must be signed in to change notification settings - Fork 113
[oneDPL] Indirectly Device Accessible Iterator Customization Point and Public Trait #620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 14 commits
d90682b
24b879d
ff940e8
0c0804b
8cff3e4
a36a006
cb102cb
bc32ce2
e7ffb99
913d555
29e209f
180a500
a852f0f
41b9828
96b1b45
dd71fdf
21b8d0f
7c76593
250aed2
696d925
b250e77
8928a06
1fff43d
59c147a
0fe3101
1d44b35
a918a45
25edb0b
b4aeaf0
4967f43
583fd52
b8a6018
311f2cb
8676878
ef67c3d
0f64be0
780f501
a57c7d7
6114c2c
536f2fa
632ac23
b5f1d8c
3fa2a02
1c71426
3b94837
699562b
1369be7
7e02e6a
7d07c92
8e32c96
5cee0b6
3970f44
d00d9cd
98a0cf4
9499cdd
d239878
4080952
00c6c7e
524f8f0
7616251
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
akukanov marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,6 +3,8 @@ | |||||||||
.. | ||||||||||
.. SPDX-License-Identifier: CC-BY-4.0 | ||||||||||
|
||||||||||
.. _iterators: | ||||||||||
|
||||||||||
Iterators | ||||||||||
--------- | ||||||||||
|
||||||||||
|
@@ -301,3 +303,109 @@ operation were applied to each of these iterators. The types ``T`` within the te | |||||||||
|
||||||||||
``make_zip_iterator`` constructs and returns an instance of ``zip_iterator`` | ||||||||||
using the set of source iterators provided. | ||||||||||
|
||||||||||
.. _iterators-passed-directly: | ||||||||||
|
||||||||||
Customization Point for "Passed Directly" Iterators | ||||||||||
akukanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
--------------------------------------------------- | ||||||||||
|
||||||||||
Iterator types can be "passed directly" to `SYCL`_ kernels when they can inherently be dereferenced on the device while | ||||||||||
using an algorithm with a ``device_policy``. Examples of iterators which can be "passed directly" include SYCL USM | ||||||||||
shared or device memory, or iterator types like ``counting_iterator`` or ``discard_iterator`` that do not require any | ||||||||||
data to be copied to the device. An example of an iterator type that cannot be "passed directly" is a ``std::vector`` | ||||||||||
iterator, which requires the data to be copied to the device in some way prior to usage in a SYCL kernel within | ||||||||||
algorithms used with a ``device_policy``. | ||||||||||
|
||||||||||
oneDPL provides a mechanism to define whether custom iterator types can be "passed directly" to SYCL kernels. oneDPL | ||||||||||
queries this information at compile time to determine how to handle the iterator type when passed to algorithms with a | ||||||||||
``device_policy``. This is important because it allows oneDPL to avoid unnecessary data movement. This is achieved using | ||||||||||
the ``is_passed_directly_in_onedpl_device_policies`` Argument-Dependent Lookup (ADL) customization point and the public | ||||||||||
trait ``is_passed_directly_to_device[_v]``. | ||||||||||
|
||||||||||
ADL Customization Point: ``is_passed_directly_in_onedpl_device_policies`` | ||||||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||||||||||
|
||||||||||
A free function ``is_passed_directly_in_onedpl_device_policies(IteratorT)`` may be defined, which accepts an argument | ||||||||||
of type ``IteratorT`` and returns a type with the characteristics of ``std::true_type`` if ``IteratorT`` can be | ||||||||||
"passed directly" to SYCL kernels, or alternatively returns a type with the characteristics of ``std::false_type`` | ||||||||||
otherwise. The function must be defined in one of the valid search locations for ADL lookup, which includes the | ||||||||||
namespace of the definition of the iterator type ``IteratorT``. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sentence sounds a bit awkward to me. ADL last letter already means lookup. Also, "valid search locations" is a sort of unusual. How about this:
Suggested change
You may leave this part, if you think it's useful: "... , which includes the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Taken, I removed the second part. It doesn't really make sense after the edit. Its more something for the documentation than the spec. |
||||||||||
|
||||||||||
The function ``is_passed_directly_in_onedpl_device_policies`` may be used by oneDPL to determine whether the iterator | ||||||||||
type can be "passed directly" to SYCL kernels by interrogating its return type at compile time only. It shall not be | ||||||||||
called by oneDPL outside a ``decltype`` context to determine the return type. This means that overloads may be provided | ||||||||||
as forward declarations only, without a body defined. ADL lookup is used to determine which function overload to use | ||||||||||
according to the rules in the `C++ Standard`_. Therefore, derived iterator types without an overload for their exact | ||||||||||
type will match their most specific base iterator type if such an overload exists. | ||||||||||
|
||||||||||
The default implementation of ``is_passed_directly_in_onedpl_device_policies`` marks the following iterators as | ||||||||||
"passed directly": | ||||||||||
* Pointers (to handle USM pointers) | ||||||||||
* Iterators with the ``using is_passed_directly = std::true_type`` trait | ||||||||||
akukanov marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
* Iterators to USM shared allocated ``std::vector``-s when the allocator type is knowable from the iterator type | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it ever a case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In practice, with a good amount of certainty with some compilers, yes. However, its a good question if its worth mentioning in the specification, since it is not always knowable (and not 100% knowable I believe). How it looks in the oneDPL's implementation currently: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Think of that as of specification, not as of documentation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In practice, oneDPL's implementation is relying upon standard library implementation details which are not part of the C++ standard library specification of In practice, it would be quite unlikely that a standard library implementation could / would have a From a specification perspective, it doesn't belong, I think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've removed the line for now, but I'm open to discussion of course. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, if we speak about As you can see There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we re-introduce something like this, we can describe it with |
||||||||||
* ``std::reverse_iterator<IteratorT>`` when ``IteratorT`` is "passed directly" | ||||||||||
|
||||||||||
oneDPL defines the "passed directly" behavior for its custom iterators as follows: | ||||||||||
* ``counting_iterator`` and ``discard_iterator``: Always "passed directly". | ||||||||||
* ``permutation_iterator``: "Passed directly" if both its source iterator and its index map are "passed directly". | ||||||||||
* ``transform_iterator``: "Passed directly" if its source iterator is "passed directly". | ||||||||||
* ``zip_iterator``: "Passed directly" if all base iterators are "passed directly". | ||||||||||
|
||||||||||
|
||||||||||
Public Trait: ``is_passed_directly_to_device[_v]`` | ||||||||||
++++++++++++++++++++++++++++++++++++++++++++++++++ | ||||||||||
|
||||||||||
The public trait ``oneapi::dpl::is_passed_directly_to_device[_v]`` can be used to query whether an iterator type is | ||||||||||
"passed directly" to SYCL kernels. The trait is defined in ``<oneapi/dpl/iterator>``. | ||||||||||
|
||||||||||
``oneapi::dpl::is_passed_directly_to_device<T>`` evaluates to a type with the characteristics of ``std::true_type`` if | ||||||||||
``T`` can be "passed directly" to SYCL kernels, otherwise it evaluates to a type with the characteristics of | ||||||||||
``std::false_type``. | ||||||||||
|
||||||||||
``oneapi::dpl::is_passed_directly_to_device_v<T>`` is a ``constexpr bool`` that evaluates to ``true`` if ``T`` can be | ||||||||||
"passed directly" to SYCL kernels, otherwise it evaluates to ``false``. | ||||||||||
|
||||||||||
Example | ||||||||||
+++++++ | ||||||||||
|
||||||||||
.. code:: cpp | ||||||||||
|
||||||||||
namespace usr | ||||||||||
{ | ||||||||||
struct pass_dir_it | ||||||||||
{ | ||||||||||
/* unspecified user definition of a "passed directly" iterator */ | ||||||||||
}; | ||||||||||
|
||||||||||
std::true_type | ||||||||||
is_passed_directly_in_onedpl_device_policies(pass_dir_it); | ||||||||||
|
||||||||||
struct no_pass_dir_it | ||||||||||
{ | ||||||||||
/* unspecified user definition of a non "passed directly" iterator */ | ||||||||||
}; | ||||||||||
|
||||||||||
std::false_type | ||||||||||
is_passed_directly_in_onedpl_device_policies(no_pass_dir_it); | ||||||||||
} | ||||||||||
|
||||||||||
static_assert(oneapi::dpl::is_passed_directly_to_device_v<usr::pass_dir_it> == true); | ||||||||||
static_assert(oneapi::dpl::is_passed_directly_to_device_v<usr::no_pass_dir_it> == false); | ||||||||||
|
||||||||||
// Example with base iterators and ADL overload as a hidden friend | ||||||||||
template <typename It1, typename It2> | ||||||||||
struct it_pair | ||||||||||
{ | ||||||||||
It1 first; | ||||||||||
It2 second; | ||||||||||
friend auto is_passed_directly_in_onedpl_device_policies(it_pair) -> | ||||||||||
std::conjunction<oneapi::dpl::is_passed_directly_to_device<It1>, | ||||||||||
oneapi::dpl::is_passed_directly_to_device<It2>>; | ||||||||||
}; | ||||||||||
|
||||||||||
static_assert(oneapi::dpl::is_passed_directly_to_device_v<it_pair<usr::pass_dir_it, usr::pass_dir_it>> == true); | ||||||||||
static_assert(oneapi::dpl::is_passed_directly_to_device_v<it_pair<usr::pass_dir_it, usr::no_pass_dir_it>> == false); | ||||||||||
|
||||||||||
|
||||||||||
.. _`C++ Standard`: https://isocpp.org/std/the-standard | ||||||||||
.. _`SYCL`: https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html |
Uh oh!
There was an error while loading. Please reload this page.