Could std::extents<> be iterable?
I don't know whether this is the right place for such comments, please let me know if I should move this discussion elsewhere.
I believe it would make a lot of sense to have std::extents be iterable and yield valid nd indices for a basic_mdspan using this extent.
Typically, one would write (with my_span a potentially multi-D mdspan):
std::mdspan<...> my_span(...);
for (auto&& ii: my_span.extents() ) {
do_something_with(my_span[ii]);
}
From a usability point of view, this would be a huge plus, but maybe this could not be such from a performance point of view:
extents<>::iteratorshould include all but the last boundary in addition to the iterator itself in order to be able to yield a validstd::array<size_t, ...>making it a potentially bloated type,- the compilers might not be able to analyze this as good as a set of nested for loops.
Has there been any investigation regarding this or not?
I shouldn't speak for @dhollman or @crtrott , but certainly we've discussed this. The main issue is that an iterator over a flattened multidimensional index space would need state. This would complicate parallelization and compiler optimizations. Also, the iteration order should depend on the layout for best performance, not just on the extents.
The main issue is that an iterator over a flattened multidimensional index space would need state.
Indeed, this is the main issue. At least if the operator*of the iterator is to return a std::array<size_t, N> to use as an index.
Another way that could be investigated is whether something different could be returned so as to skip the AccessorPolicy manipulation of basic_mdspan::operator[].
Also, the iteration order should depend on the layout for best performance, not just on the extents.
Sure, however the reason I see for iterating over the extent rather than over the mdspan itself is to iterate over the index space and thus be able to combine access to multiple spans at once:
std::mdspan<...> my_span1(...);
std::mdspan<...> my_span2(...);
for (auto&& ii: my_span.extents() ) {
combine(my_span1[ii], my_span2[ii]);
}
In that case, there is no way to ensure both access can be efficient.
I would argue this is not an issue and it should be up to the user to choose an efficient layout according to her hardware and the way she chooses to iterate (one could also imagine adapters to change this iteration order in a std::ranges fashion).
This would be very similar to what you did in Kokkos where the iteration order is basically fixed, but what changes depending on the hardware is the iteration order.
Sure, however the reason I see for iterating over the
extentrather than over themdspanitself is to iterate over the index space and thus be able to combine access to multiple spans at once....
Right, one will have to decide which mdspan's iteration order one prefers, but one can do that by picking an mdspan and querying its layout. I'm not sure if it makes sense to have a "common iteration order" for all mdspan with the same extents. Iteration order and layout are always tied together, even if one must pick a particular layout's iteration order and ignore the rest.
Note that we got now cartesian product on its way. As a first step you can create a cartesion product of iota_views of the extents. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2374r1.html
Note that we got now cartesian product on its way. As a first step you can create a cartesion product of iota_views of the extents. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2374r1.html
I just attended Bryce Adelstein Lelbach presentation at P3HPC where I noticed that. This is very exiting indeed!