Conversation
ece2592 to
e2f47b2
Compare
| #endif | ||
| #include <array> | ||
| #include <type_traits> | ||
| #include <stdexcept> |
There was a problem hiding this comment.
Nothing in this header threw an std::exception subclass before. Furthermore, the only reason this code now throws an exception is to trigger a call to terminate in a noexcept function.
Would you consider just calling std::abort as before? Alternately, would you consider adding a configurable precondition violation handler (e.g., a macro that takes a message and just calls std::abort by default)?
There was a problem hiding this comment.
Would you consider just calling std::abort as before? Alternately, would you consider adding a configurable precondition violation handler (e.g., a macro that takes a message and just calls std::abort by default)?
Sure that sounds like a better approach. I'm also wondering if extents.hpp is the right location for the terminate_if_invalid_strides function. Maybe layout_stride.hpp is a better place?
| static_assert(std::is_same<Layout, layout_left>::value or | ||
| std::is_same<Layout, layout_right>::value | ||
| , ""); |
There was a problem hiding this comment.
Would you consider adding a nonempty message here?
| template <std::size_t N> | ||
| struct with_rank {}; |
There was a problem hiding this comment.
Would you consider making this an alias of std::integral_constant, so as to avoid more instantiations of types?
|
Thanks for the contribution! There are some nice refactorings in there as well. @crtrott et al. will likely want to comment.
|
I've only tested with the tests defined in CMake along with C++14 so far. All tests pass before and after this PR - however after this PR now builds without warnings.
Sure. |
5c44070 to
22258de
Compare
|
Thanks for making the changes! Building with C++14 results in the following CMake error message. I think you could just change line 200 of CMakeLists.txt ( Line 200 in 0e6a69d to something like |
22258de to
38d3f2f
Compare
I disabled benchmarking for C++14 using the same approach for C++23 (i.e. via matrix settings in |
crtrott
left a comment
There was a problem hiding this comment.
This looks pretty good. Finally found sufficient time to review it. The new macros are not a bad idea, but I think they should all be IMPL macros.
|
I will rebase this and merge my suggestions. |
|
@oliverlee FYI: I rebased and force pushed. I'd like to get this in before I work on more of the features for C++26. |
|
Not sure why the death tests are failing now - they were fine a few months back. I'll probably have time to look into it tomorrow. |
|
They passed now. We might have changed Debug to Release build at some point and so the rebase made them fail. |
|
It should be possible to enable precondition checks in release mode with a preprocessor macro - I imagine this is enabled only for tests and disabled for benchmarks. It shouldn't be too much trouble to do in a separate PR if you want to merge this PR and use it as a base for c++26 stuff. |
|
@crtrott It looks like the macro in I've created two commits - please squash or do whatever is normal for this repo. |
|
Thanks! I had overlooked that. That said I am not sure it's the best way to go about this. Now the tests never take the code path where the preconditions are skipped. Maybe instead we should have a mix of debug and non-debug test configs. |
|
Also I am waiting for a second review to finish (should happen latest by Monday I pinged appropriate people in my team). |
Same - whatever makes the most sense to you in terms of maintenance. I've seen precondition tests defined in a separate test file. That could remove the need to conditionally define test cases with |
|
It could make sense to separate them out. We had some platforms where the death tests never fully worked ... |
There are only a few It makes sense to do it earlier rather than later if this is approach you want to pursue. |
|
Yeah let's do it. Do you have time to tackle that? If not I might get around to it some point this weekend. |
Maybe this afternoon? If not, also this weekend. |
|
Sounds good. Also I send you an invite to our slack channel in case you are interested. |
| namespace detail { | ||
|
|
||
| template <bool check = MDSPAN_IMPL_CHECK_PRECONDITION> | ||
| constexpr void precondition(const char* cond, const char* file, unsigned line) |
There was a problem hiding this comment.
I think this needs to be decorated with MDSPAN_FUNCTION
There was a problem hiding this comment.
Did you consider tag dispatching instead ,having two non templated overloads
MDSPAN_FUNCTION constexpr void precondition(std::false_type /*checked*/, const char* /*cond*/, const char* /*file*/, unsigned /*line*/) { /* do nothing */ }
MDSPAN_FUNCTION constexpr void precondition(std::true_type /*checked*/, const char* cond, const char* file, unsigned line) { MDSPAN_IMPL_PRECONDITION_VIOLATION_HANDLER(cond, file, line); }There was a problem hiding this comment.
I might have a while back? Not sure.
But I tested it out just now, and this approach produces warnings with Clang and GCC:
Clang-18:
.../mdspan/include/mdspan/../experimental/__p0009_bits/macros.hpp:142:16: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
142 | constexpr void precondition(std::true_type, const char* cond, const char* file, unsigned line)
GCC-11:
.../mdspan/include/mdspan/../experimental/__p0009_bits/macros.hpp:120:81: error: call to non-‘constexpr’ function ‘void Kokkos::detail::default_precondition_violation_handler(const char*, const char*, unsigned int)’
There was a problem hiding this comment.
I expect the issue is the constexpr specifier
There was a problem hiding this comment.
I suppose you needed it to be call it in other functions that themselves are callable in a constant expression...
| namespace MDSPAN_IMPL_STANDARD_NAMESPACE { | ||
| namespace detail { | ||
|
|
||
| inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) |
There was a problem hiding this comment.
Fine by me but just noting that the default handler would not work with CUDA/HIP
There was a problem hiding this comment.
Please feel free to make any changes if CUDA/HIP compatibility is necessary.
There was a problem hiding this comment.
printf works just fine with CUDA; it's HIP that's broken lol ; - )
There was a problem hiding this comment.
it is a fprintf and it is qualified so there is no way it works on CUDA. As far as I know HIP behaves just the same as CUDA here.
| layout_padded_constants<typename _OtherMapping::layout_type, | ||
| _ExtentsType>::padded_stride_idx; | ||
| constexpr auto extent_to_pad_idx = layout_padded_constants<typename _OtherMapping::layout_type, _ExtentsType>::extent_to_pad_idx; | ||
| assert(other_mapping.stride(padded_stride_idx) == other_mapping.extents().extent(extent_to_pad_idx)); |
There was a problem hiding this comment.
Should we not be using MDSPAN_IMPL_PRECONDITION here?
There was a problem hiding this comment.
Sure let's do that.
| target_link_libraries(${name} mdspan gtest_main) | ||
| add_test(${name} ${name}) | ||
| endmacro() | ||
| set_property(TARGET ${name} PROPERTY COMPILE_WARNING_AS_ERROR ON) |
There was a problem hiding this comment.
I am not necessarily opposed to this but IMO it does not belong to this PR
There was a problem hiding this comment.
This change is related to C++14 support to some degree - otherwise C++17 language features are still usable with some compilers when building for C++14. But I also see that the impact of this change has wider consequences.
What do you think about breaking out this change into a separate PR and rebasing this PR on top of that? I can do that later this evening - or feel free to change this PR as you see fit.
There was a problem hiding this comment.
Christian did you mean to keep this?
| { | ||
| (void)std::fprintf(::stderr, "%s:%u: precondition failure: `%s`\n", file, line, cond); | ||
| std::abort(); | ||
| } |
There was a problem hiding this comment.
I don't know how HIP or SYCL work, but the following should be fine for CUDA. Note that in device code, printf may have a performance cost even if it is never called at run time. (For example, the compiler may need to reserve registers for it.)
| { | |
| (void)std::fprintf(::stderr, "%s:%u: precondition failure: `%s`\n", file, line, cond); | |
| std::abort(); | |
| } | |
| { | |
| #if defined(__CUDA_ARCH__) | |
| # if ! defined(NDEBUG) | |
| printf("%s:%u: precondition failure: `%s`\n", file, line, cond); | |
| assert(false); | |
| # endif | |
| #else | |
| fprintf(stderr, "%s:%u: precondition failure: `%s`\n", file, line, cond); | |
| assert(false); | |
| #endif | |
| } |
There was a problem hiding this comment.
HIP works the same as Cuda. For SYCL (oneAPI), you would need to use sycl::ext::oneapi::experimental::printf.
nmm0
left a comment
There was a problem hiding this comment.
I'm good with almost everything, just lets keep the padded layout stuff isolated (since it requires C++17 anyway)
|
I just noticed that this requires CXX Extensions for GCC. I.e. -std=gnu++14 - it doesn't work with -std=c++14. Do you consider that acceptable? |
Use the `_MDSPAN_FOLD_AND` macro to avoid using fold expressions when building for C++14.
Add an empty message to static assert in `layout_padded_fwd.hpp` to avoid use of C++17 extensions when building for C++14.
Replace use of constexpr if in headers used to implement p0009 in order to allow compilation for C++14 without C++17 extensions.
Move test cases that test preconditions with `ASSERT_DEATH` to separate test files. This allows other (non-precondition) tests to be compiled with or without preconditions. CMake test targets will enable preconditions during compilation if passed the option `ENABLE_PRECONDITIONS`. This only requires moving a single test case from `test_layout_ctors` - `test_alternate_precondition_violation_handler` and `test_macros` are test files have been written primary to test preconditions.
Do you know what requires extensions? I didn't intend for that and I believe I am only using -std=c++14 in projects using mdspan (however, those don't use CMake). |
|
Its now fixed. |
| MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) | ||
| { | ||
| printf("%s:%u: precondition failure: `%s`\n", file, line, cond); | ||
| assert(0); |
There was a problem hiding this comment.
Please confirm that you did not see issue with Clang as the CUDA compiler.
There was a problem hiding this comment.
Yeah I couldn't find a variant which fails and we will use in Kokkos Kokkos::abort anyway.
| target_link_libraries(${name} mdspan gtest_main) | ||
| add_test(${name} ${name}) | ||
| endmacro() | ||
| set_property(TARGET ${name} PROPERTY COMPILE_WARNING_AS_ERROR ON) |
There was a problem hiding this comment.
Christian did you mean to keep this?
|
|
||
| TEST(TestMdspan, MdspanSizeReturnTypeAndPrecondition) | ||
| { | ||
| (void) test_info_; |
dalg24
left a comment
There was a problem hiding this comment.
Good enough.
Thank you Oliver.
I've updated the P0009 headers to compile without C++17 extensions.
For the last commit, I've dumped a few common utilities in the extents header. Please feel free to edit as desired.