Skip to content

[oneDPL][ranges] + zip_view implementation for C++20#1877

Merged
timmiesmith merged 219 commits into
mainfrom
dev/mdvorski/zip_view
Mar 17, 2026
Merged

[oneDPL][ranges] + zip_view implementation for C++20#1877
timmiesmith merged 219 commits into
mainfrom
dev/mdvorski/zip_view

Conversation

@MikeDvorskiy
Copy link
Copy Markdown
Contributor

@MikeDvorskiy MikeDvorskiy commented Sep 25, 2024

[oneDPL][ranges] + zip_view implementation for C++20. The implementation and test.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2321r2.html

  • namespace: oneapi::dpl::ranges
  • based on oneDPL device copyable tuple
  • LLVM tests added

An update:

  • rebased on the current main
  • fixed the errors within test_dangling_pointers_args_<x> and the other tests.

oneapi::dpl::experimental::ranges::zip_view
oneapi::dpl::experimental::ranges::views::zip
oneapi::dpl::experimental::views::zip

#if _ONEDPL_CPP20_RANGES_PRESENT
using oneapi::dpl::ranges::__internal::zip_view;
#else
using oneapi::dpl::__ranges::zip_view;
#endif //_ONEDPL_CPP20_RANGES_PRESENT

Added zip_view::base() method.

@MikeDvorskiy MikeDvorskiy marked this pull request as draft September 25, 2024 15:06
@MikeDvorskiy MikeDvorskiy marked this pull request as ready for review September 27, 2024 14:04
@MikeDvorskiy MikeDvorskiy force-pushed the dev/mdvorski/zip_view branch 2 times, most recently from 603daed to 80ef9c5 Compare September 30, 2024 09:50
@danhoeflinger danhoeflinger self-requested a review October 2, 2024 12:21
Copy link
Copy Markdown
Contributor

@dmitriy-sobolev dmitriy-sobolev left a comment

Choose a reason for hiding this comment

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

Let me leave just a couple of minor comments. I am going to look at the whole PR during this week.

Comment thread test/parallel_api/ranges/std_ranges_zip_view.pass.cpp Outdated
Comment thread test/parallel_api/ranges/std_ranges_zip_view.pass.cpp Outdated
Copy link
Copy Markdown
Contributor

@dmitriy-sobolev dmitriy-sobolev left a comment

Choose a reason for hiding this comment

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

What do you think about testing the following properties of zip_view/zip?

  • begin/end (they should also probably be checked if they are iterators)
  • cbegin/cend
  • front/back
  • size
  • empty
  • operator bool
  • construction:
    • ranges::zip(...)/ranges::zip_view(...)
    • empty view (views::zip())
    • another view (*move construction is not checked)
    • another zip_view
  • ranges::zip(...) is a customization point object

I assume that the functionality must match what is required from c++ standard looking at the description. That's why I suggest testing all these properties. Let me know if the implementation is expected to be more relaxed (and how if it is).

Update. I see that the PR integrates the whole LLVM test suite now. The table is not relevant now

@dmitriy-sobolev
Copy link
Copy Markdown
Contributor

dmitriy-sobolev commented Oct 18, 2024

The description says:

... based on oneDPL device copyable tuple

According to SYCL 2020, std::tuple is also device copyable (if the wrapped types are also device copyable, of course). Does it make sense to use std::tuple instead of the internal one?

@danhoeflinger
Copy link
Copy Markdown
Contributor

danhoeflinger commented Oct 18, 2024

The description says:

... based on oneDPL device copyable tuple

According to SYCL 2020, std::tuple is also device copyable (if the wrapped types are also device copyable, of course). Does it make sense to use std::tuple instead of the internal one?

The advantage here of using oneDPL's tuple is that it is trivially copyable (for trivially copyable types) which means that any class or structure which uses oneDPL's tuple can be implicitly device copyable rather than requiring a specialization of sycl::is_device_copyable (because of the tuple). std::tuple isn't specified to be trivially copyable.

The advantage is not just to avoid extra code here but also to not impose requirements on users to provide these specializations for types which are composed of a zip_view as well.

There can be downsides to using oneDPLs tuple in that it may not be as fully featured as std::tuple in some ways but I think this is the better option.

@MikeDvorskiy
Copy link
Copy Markdown
Contributor Author

MikeDvorskiy commented Oct 18, 2024

to use std::tuple instead of the internal one?

Actually, before C++23 standard library there is a problem with std::tuple swap ability. It is bigger issue that doesn't allow to use std::tuple for zip_view implementation for oneDPL C++20.

Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
@MikeDvorskiy MikeDvorskiy force-pushed the dev/mdvorski/zip_view branch 3 times, most recently from f1c08a6 to 74d52be Compare October 22, 2024 12:39
@MikeDvorskiy
Copy link
Copy Markdown
Contributor Author

MikeDvorskiy commented Oct 25, 2024

regarding > * cbegin + cend
cppreference:

cbegin
  
(C++23)
 
returns a constant iterator to the beginning of the range.
(public member function of std::ranges::view_interface<D>)
cend
  
(C++23)
 
returns a sentinel for the constant iterator of the range.
(public member function of std::ranges::view_interface<D>)

Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment on lines +192 to +196
if (x.current_ < y.current_)
return -1;
else if (x.current_ == y.current_)
return 0;
return 1; //x.current > y.current_
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why cannot we use x.current <=> y.current? Spaceship operator is undefined for some of our internal iterator types or it is undefined for internal tuple?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, spaceship operator is undefined for x.current_...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When adding comparison between internal tuples, we looked at adding spaceship and it was deemed not worth the effort at the time. We could use this as motivation for adding it, but it would require a bit of work. We would need to trigger it off of __cpp_lib_three_way_comparison >= 201907L, and in that case replace the existing comparison operators with the spaceship, to time it properly with std::tuple <=> operator

#1472 (comment)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The thought was that it wasn't worth the maintenance because we would need to implement both to support our full support matrix, and it would be only helpful for those explicitly calling <=> on the internal tuple (which is what we might want to do here as I understand it).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In any case it doesnt block zip_view productization, I believe. And we keep a spaceship operator for zip_view as is proposed.

Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h

std::sort(zip_view_sort.begin(), zip_view_sort.begin() + max_n, [](const auto& val1, const auto& val2) { return std::get<0>(val1) > std::get<0>(val2); });
for(int i = 0; i < max_n; ++i)
assert(std::get<0>(zip_view_sort[i]) == max_n - 1 - i);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Our testing framework is not adapted for assert: it defines NDEBUG during release test builds. We should either avoid that definition, or do not rely on assert in the tests.

Copy link
Copy Markdown
Contributor Author

@MikeDvorskiy MikeDvorskiy Nov 19, 2024

Choose a reason for hiding this comment

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

  1. In spite of that we are using assert in our tests more then 10 files... It seems an issue should be created.
  2. I know that a better way to use our own macro like EXPECT_TRUE f.e.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. I will create it.
  2. That sounds good. Could you do it? I see that there is still one assert in the test.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. I will create it.

Done: #1945.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

  1. done.
    And I suggest offline discussion about assert / EXPECT_TRUE / NDEBUG

Comment thread test/parallel_api/ranges/std_ranges_zip_view.pass.cpp Outdated
Comment thread test/parallel_api/ranges/std_ranges_zip_view.pass.cpp Outdated
Comment thread test/parallel_api/ranges/std_ranges_zip_view.pass.cpp Outdated
@dmitriy-sobolev
Copy link
Copy Markdown
Contributor

dmitriy-sobolev commented Nov 20, 2024

regarding > * cbegin + cend cppreference:

cbegin
  
(C++23)
 
returns a constant iterator to the beginning of the range.
(public member function of std::ranges::view_interface<D>)
cend
  
(C++23)
 
returns a sentinel for the constant iterator of the range.
(public member function of std::ranges::view_interface<D>)

zip_view is based on view_iterface, and the later does not have cbegin/cend in c++20. That means our c++20 zip_view will not have cbegin/cend, and we are not going to provide them. Is that correct understanding?

Comment thread include/oneapi/dpl/pstl/zip_view_impl.h
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
else if constexpr ((std::ranges::random_access_range<_Views> && ...))
{
auto __it = begin();
__it += size();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need to convert size() to iter_difference_t<iterator<false>> before +?

Copy link
Copy Markdown
Contributor Author

@MikeDvorskiy MikeDvorskiy Mar 10, 2026

Choose a reason for hiding this comment

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

It is made implicitly..
Explicit conversion? But it doesn't solve integer (difference type) overflow.
We may add a RT assert here for an integer overflow case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Actually, there is an assumnption in the standard: size() <= difference_type::max()
BTW, for C++20 there is std::ssize (https://en.cppreference.com/w/cpp/iterator/size.html)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, the conversion can be done implicitly, but for example with -Wsign-conversion, the clang compiler with generate warning if size() returns std::size_t and then cast it implicitly to difference_type that is std::ptrdiff_t.
I think it makes sense to avoid it by doing an explicit cast.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread include/oneapi/dpl/pstl/tuple_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/tuple_impl.h
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
MikeDvorskiy and others added 3 commits March 10, 2026 19:55
Uglification the uniglified names in zip_view_impl.h
[onedpl][zip_view] "<class'  ->  "<typename"
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
@danhoeflinger
Copy link
Copy Markdown
Contributor

@MikeDvorskiy @kboyarinov I ran a full CI which looks OK so far, still waiting for it to finish and aggregate.
I found one issue which I think is resolved with #2608, but I'm waiting on confirmation (via targeted CI run)

@MikeDvorskiy
Copy link
Copy Markdown
Contributor Author

MikeDvorskiy commented Mar 12, 2026

@MikeDvorskiy @kboyarinov I ran a full CI which looks OK so far, still waiting for it to finish and aggregate. I found one issue which I think is resolved with #2608, but I'm waiting on confirmation (via targeted CI run)

Thank you, @danhoeflinger. I'll take a look at #2608.

MikeDvorskiy and others added 2 commits March 12, 2026 12:25
[oneDPL][zip_view] minor changes: explicit cast to difference_type, the overloads for __apply_to_tuple
Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>
Comment thread include/oneapi/dpl/pstl/zip_view_impl.h Outdated
@danhoeflinger
Copy link
Copy Markdown
Contributor

danhoeflinger commented Mar 12, 2026

There are some per-commit errors showing, also the full CI showed a couple other issues:

  1. zip_view.pass:40 build error
  • Platform: icpx-2026.x.0.20260111, C++20, dpcpp/dpcpp_only backends
  • OS: multiple (amazonlinux2023, rhel9, debian11.2, rockylinux9, ubuntu22.04)
  • Error: no viable constructor or deduction guide for deduction of template arguments of
    'zip_view'
  • __nanorange::nano::views::all(data) is incompatible with the new zip_view because it does not satisfy std::ranges::view (because std::ranges::enable_view is false for nanorange types)
    Should this be guarded or is there some fix we need for nanorange views:all or zip_view?
  1. Static assertion (proposed fix: Guard static asserts for std::ranges::view #2611)
  • Tests: ALL ~22 zip_view tests (4 failures each, consistently)
  • Platform: debian11.2 , icpx-2026.x.0.20260111, 64-bit, C++20 only
  • Error: static assertion failed (build error)
    It seems like the static_assertion for cpp20_output_iterator we found earlier with GCC 10's pre-P2325R3 view concept requiring default_initializable has not fully been resolved.

MikeDvorskiy and others added 2 commits March 12, 2026 17:04
[oneDPL][zip_view] +fixes in "zip_view::end" methods
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
@MikeDvorskiy
Copy link
Copy Markdown
Contributor Author

  • Error: no viable constructor or deduction guide for deduction of template arguments of
    'zip_view'

Probably, a reason is #1877 (comment)

@kboyarinov
Copy link
Copy Markdown
Contributor

Consider a prototype that simplifies usage of __apply_to_tuple: #2613.
I don't insist on merging it

@MikeDvorskiy
Copy link
Copy Markdown
Contributor Author

MikeDvorskiy commented Mar 14, 2026

There are some per-commit errors showing, also the full CI showed a couple other issues:

@danhoeflinger, Thank you for reporting this.
Basically, the issues were triggered by a couple of incorrect commits. It has now been fixed, and the per-commit CI is green.
What types of errors still remain in the full CI at the moment?

MikeDvorskiy and others added 8 commits March 16, 2026 15:55
…PRESENT definition:

+  (__GLIBCXX__ >= 20220728)
* fix static asserts for std::ranges::view

Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>

* improve naming of input output iterator guard

Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>

* default constructor for BufferView

Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>

* guarding checks for NoDefaultCtr views

Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>

---------

Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>
* add minimal test for cpp20 zip_view

---------

Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>
---------

Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>
Co-authored-by: Mikhail Dvorskiy <mikhail.dvorskiy@intel.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Dan Hoeflinger <dan.hoeflinger@intel.com>
Copy link
Copy Markdown
Contributor

@danhoeflinger danhoeflinger left a comment

Choose a reason for hiding this comment

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

I think we can merge this.

There are a couple pending changes we could consider either before or after the milestone closes:

  1. #2624 - alternative is to have a known issue for zip_view::sentinel for gcc prior to 13.1
  2. #2613 - this is just preference / clarity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants