Skip to content

[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

Open
wants to merge 39 commits into
base: main
Choose a base branch
from

Conversation

danhoeflinger
Copy link
Contributor

@danhoeflinger danhoeflinger commented Apr 3, 2025

Specification for "indirectly device accessible iterator" customization point and public trait. Based upon proposed [RFC].(uxlfoundation/oneDPL#1999)

Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
@danhoeflinger danhoeflinger changed the title [Draft][oneDPL] Passed Directly customization point and public trait [oneDPL] Passed Directly customization point and public trait Apr 4, 2025
@danhoeflinger danhoeflinger marked this pull request as ready for review April 4, 2025 13:20
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
@akukanov akukanov added DPL enhancement New feature or request labels Apr 4, 2025
@danhoeflinger danhoeflinger changed the title [oneDPL] Passed Directly customization point and public trait [oneDPL] Device accessible content iterator customization point and public trait Apr 4, 2025
Copy link
Contributor

@rarutyun rarutyun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite a significant amount of suggestions, I think that wording is pretty good, overall. There is one place that is related to the design, where we need to be careful to not prohibit some intendent use-cases.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A free function ``is_onedpl_device_accessible_content_iterator(IteratorT)`` may be defined, which accepts an argument
of type ``IteratorT`` and returns a type with the characteristics of ``std::true_type`` if ``IteratorT`` refers to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not true for a generic case. As I mentioned, I believe std::conjunction is an important use case. However, std::conjunction might not have std::true_type or std::false_type characteristics at all.

I believe that this sentence about characteristics has a perfect fit to where you describe is_device_accessible_content_iterator trait itself instead of the current wording, which is "... evaluates to a type...". I would just say "...has characteristics of std::true_type ..."

Here we need something else. Don't have immediate suggestions, though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, std::conjunction might not have std::true_type or std::false_type characteristics at all.

If it is used with true_type/false_type or derivatives, it will:

The specialization std::conjunction<B1, ..., BN> has a public and unambiguous base that is

  • if sizeof...(B) == 0, std::true_type;
  • otherwise the first type Bi in B1, ..., BN for which bool(Bi::value) == false, or BN if there is no such type.

And that's exactly our goal I believe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose I don't know exactly what we mean by "characteristics of std::true_type" if a std::conjunction or similar types will not qualify.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conjunction, disjunction and possibly negation (though, I am not sure) are the only exceptions I am aware of. All other traits have characteristics of either true_type or false_type because they inherit from bool_constant

Copy link
Contributor

@akukanov akukanov Apr 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose I don't know exactly what we mean by "characteristics of std::true_type" if a std::conjunction or similar types will not qualify.

The wording "with a base characteristic of" is used in a few places in the C++ standard, for example in https://eel.is/c++draft/meta.unary:

Subclause [meta.unary] contains templates that may be used to query the properties of a type at compile time.
Each of these templates shall be a Cpp17UnaryTypeTrait with a base characteristic of true_type if the corresponding condition is true, otherwise false_type.

My understanding of this wording is: even though it is not a true_type or false_type, it has all the same characteristics as these types and can be used as such. Practically it means that the trait class inherits either true_type or false_type (maybe indirectly).

In my comment above, I say that std::conjunction also falls into this category if the chosen template parameter does. Though the standard does not prohibit to use other types with std::conjunction, typical arguments it is used with will be traits etc. classes that inherit bool_constant. Therefore requiring that the return type of our ADL customization function should have these characteristics does not preclude the use of std::conjunction, but limits what types can be passed to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding of this wording is: even though it is not a true_type or false_type, it has all the same characteristics as these types and can be used as such.

Actually, it's even more strict - the standard requires public inheritance, see https://eel.is/c++draft/meta.rqmts#:Cpp17UnaryTypeTrait:

It shall be ... publicly and unambiguously derived, directly or indirectly, from its base characteristic ... The member names of the base characteristic shall not be hidden and shall be unambiguously available ....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is see, thanks for the clarification. I think I agree that our current formulation makes sense then, with a small tweak to the language perhaps to follow the example language you provided.

Unless we have a compelling example to allow conjunction disjunction negation which use something other than types with the base characteristic of a bool_constant, I think simplicity is better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To follow up here, I've adjusted the language slightly, but think this simple version is best without making it more broad. I've not been able to come up with any real compelling case for conjunction or disjunction of an integral_constant which is not a bool_constant worth making this language more complex.

However, I think a valid implementation could easily accommodate arbitrary usage of conjunction and disjunction, ensuring that the public trait is always a bool_constant.

@@ -174,6 +200,10 @@ to index into the index map. The corresponding value in the map is then used
to index into the value set defined by the source iterator. The resulting lvalue is returned
as the result of the operator.

``permutation_iterator`` are SYCL device-copyable if both the ``SourceIterator`` and the ``IndexMap``
are SYCL device-copyable, and are always "device accessible content iterators" if both the ``SourceIterator``
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
are SYCL device-copyable, and are always "device accessible content iterators" if both the ``SourceIterator``
are SYCL device-copyable, and are "device accessible content iterators" if both the ``SourceIterator``

"Always" word seems redundant to me. The same comment is applicable for the iterators below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed all instances of this.

Comment on lines 362 to 363
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``.
Copy link
Contributor

Choose a reason for hiding this comment

The 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
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``.
otherwise. The function must be discoverable by ADL, which includes the
namespace of the definition of the iterator type ``IteratorT``.

You may leave this part, if you think it's useful: "... , which includes the
namespace of the definition of the iterator type IteratorT" but it also might be removed, I think. They choice is yours.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 public trait ``oneapi::dpl::is_device_accessible_content_iterator[_v]`` can be used to query whether an iterator
is a "device accessible content iterator". The trait is defined in ``<oneapi/dpl/iterator>``.

``oneapi::dpl::is_device_accessible_content_iterator<T>`` evaluates to a type with the characteristics of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still don't like this style of writing after a template name because it confuses (probably experienced) C++ users. Is the any chance we will define the API properly?

Something like

The following class template and variable template are defined in namespace oneapi::dpl:

template <typename T>
struct is_device_accessible_content_iterator;

template <typename T>
inline constexpr bool is_device_accessible_content_iterator = is_device_accessible<T>::value;

and then the descriptive part.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted to be close to your proposal.




Public Trait: ``oneapi::dpl::is_device_accessible_content_iterator[_v]``
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming suggestions to consider

  • is_passed_directly_to_device (perhaps obsolete)
  • is_device_accessible_iterator
  • is_indirectly_device_accessible

For the last one it might be is_device_indirectly_accessible; not sure what is more accurate from English perspective. But the last proposed option (by me) is my favorite, so far. It also corelates with several C++20 concepts, e.g., indirectly_writable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like is_device_accessible_iterator because I think there is a difference between the iterator being accessible and its content it refers to being accessible. However, is_indirectly_device_accessible is more clear and concise than what is currently in the PR.

Copy link
Contributor

@akukanov akukanov Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with is_indirectly_device_accessible, but we need to get feedback from the customers (that applies to any name(s) we eventually propose).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also thinking that is_device_accessible_iterator partially reflects the purpose. On the other hand we pass iterators to eventually get data from it, right? :)

That's how the idea about is_indirectly_device_accessible comes to my mind. Since three of us like it we should probably reach customers to get feedback (as Alexey suggested). Whether we should change "device accessible content iterators", I am not sure. Perhaps, we should (if we agree on the new name) but I don't have a very strong preference

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I adjusted the name here in the spec.




Public Trait: ``oneapi::dpl::is_device_accessible_content_iterator[_v]``
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also thinking that is_device_accessible_iterator partially reflects the purpose. On the other hand we pass iterators to eventually get data from it, right? :)

That's how the idea about is_indirectly_device_accessible comes to my mind. Since three of us like it we should probably reach customers to get feedback (as Alexey suggested). Whether we should change "device accessible content iterators", I am not sure. Perhaps, we should (if we agree on the new name) but I don't have a very strong preference

@@ -64,6 +86,8 @@ counter; dereference operations cannot be used to modify the counter. The arithm
operators of ``counting_iterator`` behave as if applied to the values of Integral type
representing the counters of the iterator instances passed to the operators.

``counting_iterator`` are SYCL device-copyable, and are "device accessible content iterators".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was fine with keeping "always for counting_iterator and discard_iterator (I think I wrote something like "iterator below". But how it's right now is also good. Please keep it as is.

I have another suggestion somewhere you use "<iterator_name> are" and somewhere "<iterator_name> is". I propose to align to "is" everywhere

Suggested change
``counting_iterator`` are SYCL device-copyable, and are "device accessible content iterators".
``counting_iterator`` is SYCL device-copyable, and are "device accessible content iterators".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adjusted all of these "are" -> "is" [a]

@@ -104,6 +128,8 @@ lvalue that may be assigned an arbitrary value. The assignment has no effect on
of ``discard_iterator`` behave as if applied to integer counter values maintained by the
iterator instances to determine their position relative to each other.

``discard_iterator`` are SYCL device-copyable, and are "device accessible content iterators".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
``discard_iterator`` are SYCL device-copyable, and are "device accessible content iterators".
``discard_iterator`` is SYCL device-copyable, and are "device accessible content iterators".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adjusted all of these "are" -> "is" [a]

@@ -174,6 +200,10 @@ to index into the index map. The corresponding value in the map is then used
to index into the value set defined by the source iterator. The resulting lvalue is returned
as the result of the operator.

``permutation_iterator`` are SYCL device-copyable if both the ``SourceIterator`` and the ``IndexMap``
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
``permutation_iterator`` are SYCL device-copyable if both the ``SourceIterator`` and the ``IndexMap``
``permutation_iterator`` is SYCL device-copyable if both the ``SourceIterator`` and the ``IndexMap``

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adjusted all of these "are" -> "is" [a]

Comment on lines 391 to 393
``template <typename T> oneapi::dpl::is_device_accessible_content_iterator<T>`` evaluates to a type with the
characteristics of ``std::true_type`` if ``T`` refers to "device accessible content", otherwise it evaluates to a type
with the characteristics of ``std::false_type``.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still recommend some improvements

Suggested change
``template <typename T> oneapi::dpl::is_device_accessible_content_iterator<T>`` evaluates to a type with the
characteristics of ``std::true_type`` if ``T`` refers to "device accessible content", otherwise it evaluates to a type
with the characteristics of ``std::false_type``.
``is_device_accessible_content_iterator`` has characteristics of ``std::true_type`` if ``T`` refers to "device accessible content", otherwise it has characteristics of ``std::false_type``.

If you want to keep template <typename T> at the beginning, that's probably fine (though, looks redundant) but please at least remove <T> after class name. Also, "evaluates to a type" sounds a little bit clunky to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

{
struct accessible_it
{
/* unspecified user definition of a iterator which refers to "device accessible content" */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* unspecified user definition of a iterator which refers to "device accessible content" */
/* unspecified user definition of a iterator which refers to "device accessible content" */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

Signed-off-by: Dan Hoeflinger <[email protected]>
formatting

Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
…accessible types (no host allocated random access data)

Signed-off-by: Dan Hoeflinger <[email protected]>
Signed-off-by: Dan Hoeflinger <[email protected]>
@danhoeflinger danhoeflinger changed the title [oneDPL] Device accessible content iterator customization point and public trait [oneDPL] indirectly device accessible iterator customization point and public trait Apr 14, 2025
@danhoeflinger danhoeflinger changed the title [oneDPL] indirectly device accessible iterator customization point and public trait [oneDPL] Indirectly Device Accessible Iterator Customization Point and Public Trait Apr 14, 2025
Signed-off-by: Dan Hoeflinger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DPL enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants