Skip to content

Conversation

@crtrott
Copy link
Member

@crtrott crtrott commented Oct 20, 2023

This fixes most everything identified in the llvm tests which is wrong with our reference implementation, and where we haven't backported fixes yet from when we contributed our implementation to LLVM.

I haven't done mdspan yet.

@crtrott
Copy link
Member Author

crtrott commented Oct 20, 2023

Outstanding FIXMEs:

../../tests/libcxx-backports/layout_left/layout_left.static_requirements.pass.cpp:  // static_assert(std::__mdspan_detail::__is_extents_v<E>); // FIXME
../../tests/libcxx-backports/layout_right/layout_right.static_requirements.pass.cpp:  //static_assert(std::__mdspan_detail::__is_extents_v<E>); //FIXME
../../tests/libcxx-backports/layout_stride/CMakeLists.txt:#mdspan_add_test(layout_stride.extents.verify) //FIXME
../../tests/libcxx-backports/layout_stride/layout_stride.ctor.strided_mapping.pass.cpp:  //test_layout<always_convertible_layout>(); //FIXME
../../tests/libcxx-backports/layout_stride/layout_stride.static_requirements.pass.cpp:  //static_assert(std::__mdspan_detail::__is_extents_v<E>); //FIXME
../../tests/libcxx-backports/mdspan/CMakeLists.txt:#mdspan_add_test(mdspan.conversion.pass) //FIXME
../../tests/libcxx-backports/mdspan/CMakeLists.txt:#mdspan_add_test(mdspan.index_operator.pass) //FIXME
../../tests/libcxx-backports/mdspan/CMakeLists.txt:#mdspan_add_test(mdspan.swap.pass) //FIXME
../../tests/libcxx-backports/mdspan/mdspan.conversion.pass.cpp:  // FIXME: these tests trigger what appears to be a compiler bug on MINGW32 with --target=x86_64-w64-windows-gnu
../../tests/libcxx-backports/mdspan/mdspan.ctor.copy.pass.cpp:  //static_assert(noexcept(MDS(m_org)) == (noexcept(H(handle))&& noexcept(M(map))&& noexcept(A(acc)))); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.ctor.default.pass.cpp:    //static_assert(noexcept(MDS()) == (noexcept(H())&& noexcept(M())&& noexcept(A()))); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.ctor.default.pass.cpp:  // static_assert(test()); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.ctor.dh_extents.pass.cpp:    //static_assert(!std::is_constructible_v<MDS, const H&, const typename M::extents_type&>); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.ctor.dh_span.pass.cpp:  //test_mdspan_ctor<mec, ac>(handle, construct_mapping(layout, std::extents<int>()), acc); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.ctor.dh_span.pass.cpp:  //test_mdspan_ctor<mec, ac>(handle, construct_mapping(layout, std::extents<unsigned, 7>()), acc); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.deduction.pass.cpp:  //ASSERT_SAME_TYPE(decltype(std::mdspan(handle, 5, SizeTIntType(6))), std::mdspan<T, std::dextents<size_t, 2>>); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //ASSERT_SAME_TYPE(decltype(m.size()), typename MDS::size_type); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //assert(!noexcept(MDS::is_always_unique())); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //assert(!noexcept(MDS::is_always_exhaustive())); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //assert(!noexcept(MDS::is_always_strided())); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //assert(!noexcept(m.is_unique())); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //assert(!noexcept(m.is_exhaustive())); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //assert(!noexcept(m.is_strided())); //FIXME
../../tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp:  //static_assert(test()); //FIXME

Comment on lines 532 to 533
for (size_type r = 0; r < m_rank; r++)
if(rhs.extent(r) != lhs.extent(r)) return false;
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
for (size_type r = 0; r < m_rank; r++)
if(rhs.extent(r) != lhs.extent(r)) return false;
for (size_type r = 0; r < m_rank; r++) {
if (rhs.extent(r) != lhs.extent(r)) {
return false;
}
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Proposing to run the whole thing through clang-format and starting to enforce it.

Copy link
Contributor

@mhoemmen mhoemmen left a comment

Choose a reason for hiding this comment

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

The one lambda with explicit template parameters [&] <size_t...> { /* ... */ } requires C++20, but it's not protected with a macro. Otherwise, this is great! : - )

Copy link
Contributor

@mhoemmen mhoemmen left a comment

Choose a reason for hiding this comment

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

AWESOME

@crtrott crtrott force-pushed the fix-standard-compliance branch from bcdb5e0 to 8328f29 Compare October 23, 2023 19:02
MDSPAN_STATIC_TEST(
std::is_constructible<LS2, AStridedLayout<true>::mapping<E1>>::value &&
std::is_convertible<AStridedLayout<true>::mapping<E1>, LS2>::value
!std::is_convertible<AStridedLayout<true>::mapping<E1>, LS2>::value
Copy link
Member Author

Choose a reason for hiding this comment

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

Only std:: layouts are convertible, everything else is explicit in the standard.

#ifdef __cpp_lib_span
MDSPAN_TEMPLATE_REQUIRES(class T, size_t N,
/* requires */ (N == m_size_dynamic))
/* requires */ (N == m_size_dynamic && N > 0))
Copy link
Member Author

Choose a reason for hiding this comment

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

needed a separate constructor to make this work warning free, and make it work in constant expressions. Same strategy as with the from std::array ctor.

/* requires */
(
_MDSPAN_TRAIT(std::is_convertible, OtherIndexType, index_type) &&
_MDSPAN_TRAIT(std::is_convertible, const OtherIndexType&, index_type) &&
Copy link
Member Author

Choose a reason for hiding this comment

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

This is what the standard says.

Copy link
Member Author

Choose a reason for hiding this comment

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

Same below. The LLVM tests catch the difference.

extents(IndexTypes...)
-> extents<size_t,
size_t((IndexTypes(), ::MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent))...>;
((void) sizeof(IndexTypes), ::MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent)...>;
Copy link
Member Author

Choose a reason for hiding this comment

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

Don't require default constructibility of IndexTypes to make the deduction guide work.

for(rank_type r=0; r<__extents.rank(); r++) {
if(stride != static_cast<index_type>(other.stride(r))) {
// Note this throw will lead to a terminate if triggered since this function is marked noexcept
throw std::runtime_error("Assigning layout_stride to layout_left with invalid strides.");
Copy link
Member Author

Choose a reason for hiding this comment

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

complains about throw in noexcept on various compilers (warning).

MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_exhaustive() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; }
Copy link
Member Author

Choose a reason for hiding this comment

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

This is what the standard says.

MDSPAN_TEMPLATE_REQUIRES(
class OtherExtents,
/* requires */ ( Extents::rank() == OtherExtents::rank())
)
Copy link
Member Author

Choose a reason for hiding this comment

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

constraint in the standard.

class OtherExtents,
/* requires */ ( Extents::rank() == OtherExtents::rank())
)
MDSPAN_INLINE_FUNCTION
Copy link
Member Author

Choose a reason for hiding this comment

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

constraint in the standard.

for(rank_type r=__extents.rank(); r>0; r--) {
if(stride != static_cast<index_type>(other.stride(r-1))) {
// Note this throw will lead to a terminate if triggered since this function is marked noexcept
throw std::runtime_error("Assigning layout_stride to layout_right with invalid strides.");
Copy link
Member Author

Choose a reason for hiding this comment

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

get rid of warning and make it work in constant expression

MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_exhaustive() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; }
Copy link
Member Author

Choose a reason for hiding this comment

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

standard says so

//----------------------------------------------------------------------------

using __strides_storage_t = std::array<index_type, extents_type::rank()>;
using __strides_storage_t = detail::possibly_empty_array<index_type, extents_type::rank()>;
Copy link
Member Author

Choose a reason for hiding this comment

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

get rid of use of std::array, for GPUs etc. actually this is what the LLVM implementation does too, will make the class empty for rank-0 with clang (where std:;array actually contains a char).

&& _MDSPAN_FOLD_AND((self.extents().extent(Idxs) == other.extents().extent(Idxs)) /* || ... */);
using common_t = std::common_type_t<index_type, typename OtherExtents::index_type>;
return _MDSPAN_FOLD_AND((static_cast<common_t>(self.stride(Idxs)) == static_cast<common_t>(other.stride(Idxs))) /* && ... */)
&& _MDSPAN_FOLD_AND((static_cast<common_t>(self.extents().extent(Idxs)) == static_cast<common_t>(other.extents().extent(Idxs))) /* || ... */);
Copy link
Member Author

Choose a reason for hiding this comment

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

these and others like it eliminate warning for different signedness.

MDSPAN_INLINE_FUNCTION
static constexpr std::array<index_type, extents_type::rank()> return_strides(const __strides_storage_t& s) {
return std::array<index_type, extents_type::rank()>{s[Idxs]...};
}
Copy link
Member Author

Choose a reason for hiding this comment

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

need this becasue we don't store a std::array for strides anymore.

: __members{
#else
: __base_t(__base_t{__member_pair_t(
#endif
Copy link
Member Author

Choose a reason for hiding this comment

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

Need to create "layout_right" strides in default construction.

!(std::is_convertible<typename StridedLayoutMapping::extents_type, extents_type>::value &&
(detail::__is_mapping_of<layout_left, StridedLayoutMapping> ||
detail::__is_mapping_of<layout_right, StridedLayoutMapping> ||
detail::__is_mapping_of<layout_stride, StridedLayoutMapping>))
Copy link
Member Author

Choose a reason for hiding this comment

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

this was just wrong.

Copy link
Member Author

Choose a reason for hiding this comment

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

LLVM tests catch this.

} else {
return required_span_size() == __get_size(extents(), std::make_index_sequence<extents_type::rank()>());
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Now fully implement corner case required_span_size.

using common_t = std::common_type_t<index_type, typename StridedLayoutMapping::index_type>;
for(rank_type r = 0; r < extents_type::rank(); r++)
strides_match = strides_match && (static_cast<common_t>(x.stride(r)) == static_cast<common_t>(y.stride(r)));
}
Copy link
Member Author

Choose a reason for hiding this comment

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

get rid of warning

_MDSPAN_TRAIT(std::is_convertible, SizeType, index_type) &&
_MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, SizeType) &&
_MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) &&
_MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) &&
Copy link
Member Author

Choose a reason for hiding this comment

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

this is what the standard actually says.

@crtrott crtrott merged commit b186529 into kokkos:stable Oct 26, 2023
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.

2 participants