Accessing a row of a std::mdspan as std::span
Asked Answered
A

1

8

I'm trying out the Kokkos reference mdspan implementation to see if it could be used to simplify some bits of code in our codebase. One thing that I would have intuitively assumed to be possible is to pick a row of a two dimensional std::mdspan and assign it to a std::span, e.g. somewhat like

float* data = ...

std::mdspan matrix (data, 2, 5);

std::span vector = matrix[0]; // <-- should be a std::span<float, std::dynamic_extent> viewing row 0 of matrix

After some research I didn't find an obvious straightforward way to achieve that, neither with member functions of mdspan nor with free functions from the std library. The only possibility I see at the moment I going back to the raw pointer level and write my own free functions to do that, which is not really as elegant as I expected. Am I overlooking something or is that really no feature of mdspan?

Autosome answered 15/8, 2023 at 12:59 Comment(5)
Maybe submdspan can help.Underglaze
Thanks, but this does not offer direct conversion to std::span, right?Autosome
The 5 can not conveniently be a template parameter because it is a runtime variable. By providing the 5 to the constructor of matrix there is no reasonable way to make the mdspan aware at compile time that the second extent always has 5 elements. The best you can do here is std::span<float, std::dynamic_extent>.Vento
Ah yes of course @Mestkon. I'm aware of that, fixed it in the question aboveAutosome
Rows are not guaranteed to be contiguous in mdspan, e.g. std::layout_left will give contiguous columns but strided rows. For this reason there can't be a direct conversion to std::span. Maybe one could add a direct conversion to a std::ranges::stride_view in the future but even that wont work for some custom layouts.Hoofed
C
4

You can slice the original 2d-mdspan into a 1-d mdspan through C++26 std::submdspan().

Since the underlying sequence of result mdspan is contiguous, it can be used to construct the std::span

float* data = ...;

std::mdspan matrix(data, 2, 5);

std::mdspan row0 = std::submdspan(matrix, 0, std::full_extent);
std::span vector0(row0.data_handle(), row0.size()); // row 0 of matrix

std::mdspan row1 = std::submdspan(matrix, 1, std::full_extent);
std::span vector1(row1.data_handle(), row1.size()); // row 1 of matrix

Demo using reference mdspan implementation.

Carbazole answered 6/10, 2023 at 18:22 Comment(1)
Each row is only contiguous when assuming std::layout_right or similar. For std::layout_left or similar above code will produce wrong results. This is probably the reason why there is no nicer general API for this.Hoofed

© 2022 - 2024 — McMap. All rights reserved.