-
Notifications
You must be signed in to change notification settings - Fork 69
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
Line 132 of layout_right.hpp seems wrong #229
Comments
The conversion operators from layout_stride for both layout_left and layout_right were missing a static_cast and also were not marked noexcept. I now guard the precondition check with NDEBUG. Note: the throw in there is legal: it will result in a termination if triggered since the function is marked noexcept.
The most appropriate thing is probably a static cast to index_type (which is a member of the class). I also fixed the missing noexcept which is in the standard but was not in the implementation. The precondition check is now only done with NDEBUG not being defined. |
The conversion operators from layout_stride for both layout_left and layout_right were missing a static_cast and also were not marked noexcept. I now guard the precondition check with NDEBUG. Note: the throw in there is legal: it will result in a termination if triggered since the function is marked noexcept.
The conversion operators from layout_stride for both layout_left and layout_right were missing a static_cast and also were not marked noexcept. I now guard the precondition check with NDEBUG. Note: the throw in there is legal: it will result in a termination if triggered since the function is marked noexcept.
Address issue #229 and fix missing noexcept
@riclarsson can you check that this is fixed for you? Also what do you mean with |
About the updated code @crtrott I've since gone on to not allow turning a strided However, I think the solution is not optimal. The following code-snippet demonstrates a new problem: std::vector<double> v(6);
for (std::int64_t i = 0; i < 6; i++)
v[i] = static_cast<double>(1 + 10 * i);
for (std::int64_t i = 0; i < 6; i++)
std::cout << v[i] << ' ';
std::cout << '\n';
stdx::mdspan<double, stdx::dextents<std::int64_t, 2>> m(
v.data(), std::array<std::int64_t, 2>{3, 2});
for (std::int64_t i = 0; i < 3; i++)
for (std::int64_t j = 0; j < 2; j++)
std::cout << m(i, j) << ' ';
std::cout << '\n';
stdx::mdspan<double, stdx::dextents<std::int64_t, 1>, stdx::layout_stride>
vs = stdx::submdspan(m, stdx::full_extent, 0);
for (std::int64_t i = 0; i < 3; i++)
std::cout << vs[i] << ' ';
std::cout << '\n';
stdx::mdspan<double, stdx::dextents<std::int64_t, 1>> ve(vs);
for (std::int64_t i = 0; i < 3; i++)
std::cout << ve[i] << ' ';
std::cout << '\n'; This compiles and runs to the end using CMake Release flags for both GCC12 and Clang15. The output is: 1 11 21 31 41 51
1 11 21 31 41 51
1 21 41
1 11 21 So the exhaustive With the RelWithDebInfo CMake mode, the call terminates. It also produces a much nastier warning than I was having with the integer comparison. I honestly think it is a bad idea to mark this particular constructor About the You didn't have, or I didn't find, |
Ah I see the warning ... I guess we could just abort/terminate instead of throw. |
@crtrott About std::vector<double> v(3);
for (std::int64_t i = 0; i < 3; i++)
v[i] = static_cast<double>(1 + 10 * i);
stdx::mdspan<double, stdx::dextents<std::int64_t, 1>> ve{
v.data(), std::array<std::int64_t, 1>{3}};
auto rvs = stdx::submdspan(
ve,
stdx::strided_slice<std::int64_t, std::int64_t, std::int64_t>{2, 3, -1});
auto rvs2 = stdx::submdspan(
ve,
stdx::strided_slice<std::int64_t, std::int64_t, std::int64_t>{2, 2, -2});
for (std::int64_t i = 0; i < 3; i++)
std::cout << ve[i] << ' ';
std::cout << '\n';
for (std::int64_t i = 0; i < rvs.extent(0); i++)
std::cout << rvs[i] << ' ';
std::cout << '\n';
for (std::int64_t i = 0; i < rvs2.extent(0); i++)
std::cout << rvs2[i] << ' ';
std::cout << '\n'; should intuitively output:
Instead, it only outputs:
I would have expected that this is what observably happens when the code above is run: std::vector<double> v(3);
for (std::int64_t i = 0; i < 3; i++)
v[i] = static_cast<double>(1 + 10 * i);
stdx::mdspan<double, stdx::dextents<std::int64_t, 1>> ve{
v.data(), std::array<std::int64_t, 1>{3}};
stdx::strided_slice<std::int64_t, std::int64_t, std::int64_t> rev{2, 3, -1};
stdx::mdspan<double, stdx::dextents<std::int64_t, 1>, stdx::layout_stride>
rvs{ve.data_handle() + ve.stride(0) * rev.offset,
{std::array<std::int64_t, 1>{rev.extent},
std::array<std::int64_t, 1>{rev.stride * ve.stride(0)}}};
stdx::strided_slice<std::int64_t, std::int64_t, std::int64_t> rev2{2, 2, -2};
stdx::mdspan<double, stdx::dextents<std::int64_t, 1>, stdx::layout_stride>
rvs2{ve.data_handle() + ve.stride(0) * rev2.offset,
{std::array<std::int64_t, 1>{rev2.extent},
std::array<std::int64_t, 1>{rev2.stride * ve.stride(0)}}};
for (std::int64_t i = 0; i < 3; i++)
std::cout << ve[i] << ' ';
std::cout << '\n';
for (std::int64_t i = 0; i < rvs.extent(0); i++)
std::cout << rvs[i] << ' ';
std::cout << '\n';
for (std::int64_t i = 0; i < rvs2.extent(0); i++)
std::cout << rvs2[i] << ' ';
std::cout << '\n'; (This code-snippet of course works for any strided |
Note: none of the layouts we got support negative strides. And the strided_slice thing is not currently intended to support it either. See: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2630r2.html |
This is the relevant line:
|
@crtrott Ok, so I understand that I am more concerned about your other statement, that you do not have a layout that supports negative strides. Can you clarify? Because your implementation of Your EDIT: Not to say that I don't agree with the design. I think negative strides are a pain. If I manage to convince people I work with about that is another issue altogether that I am currently attempting. |
The C++ standard has a precondition on layout_stride constructors for strides to be larger zero, so its a precondition violation not to do that. If you instantiate it with negative strides there are likely a couple issues:
However: it is NOT against the rules to write a layout which DOES support negative strides. offset = 0;
for(rank_type r=0; r<extents_type::rank(); r++)
offset -= stride(r)<0 ? stride(r) * (extents().extent(r)-1) : 0; Required span size is then: req_span_size = offset;
for(rank_type r=0; r<extents_type::rank(); r++)
offset += stride(r)>0 ? stride(r) * (extents().extent(r)-1) : 0; And then the mapping operator would look something equivalent to this: template<class ... Indicies>
index_type operator()(Indicies ... idxs) const {
array ii{static_cast<index_type>(idxs)...};
index_type idx = offset;
for(rank_type r = 0; r<extents_type::rank(); r++) idx += ii[r] * stride(r);
return ii;
} This way you return something between zero and some max value and it all hangs together. I am not sure what exactly the determination is to figure out whether the layout is unique. I think it might be the same as for std::layout_stride but just using the abs values of the strides? Anyway does that make all sense? So the reasons we didn't support negative stride are in combination:
|
I think we resolved this issue to the degree we can. Gonna close the issue. |
…m_empty-check kokkos: fix empty matrix check in `matrix_inf_norm` kokkos#225
Hi,
I think the line should simply read
decltype(other.stride(0)) stride = 1;
. I guess you have that index type declared somewhere but I am not sure where.The problem seems to only present itself when using the
full_extent_t
stuff with indices in a non-optimal way. I need this because I am replacing code that has these features. (I also need something like a partial_extent_t but I wrote my own for that for now because I could't find anything in the documentation.)The text was updated successfully, but these errors were encountered: