Repository navigation
nvexec: forward reference results from then, upon_error and upon_stopped - #2410
alwaysprince05 wants to merge 1 commit into
Conversation
When the callable returns a reference, the kernel now stores a pointer to the referenced object in temporary storage, and the reference is passed on from that pointer. Before, the result was decay-copied, so the receiver got a prvalue while the sender advertised set_value_t(T&), and code like then(f -> int&) | then(g(int&)) did not compile. The address is only known after the kernel has run, so a reference result waits for the stream (cudaStreamSynchronize) before it is passed on. Value results are unchanged. then's set_value constraint now checks the callable against the arguments as they are passed, like upon_error already does. Fixes NVIDIA#958
|
/ok to test b5fce10 |
|
unrelated: would you mind looking at the failure on #2277? my CUDA setup is borked at the moment. i don't know why that PR would cause the |
|
Thanks for the review! Sure, I'll look at #2277. From the CI log, the crash is in the stream scheduler part of About the red checks here: all 14 failed before anything was compiled. Some got a 504 from github.com while |
Fixes #958.
When the callable passed to
nvexec::then,upon_errororupon_stoppedreturns a reference, the sender advertisesset_value_t(T&)but the receiver was sent a decayed copy (std::move(*d_result)). So something likefailed to compile on a stream scheduler (
common.cuh:776: no matching function for call to object of type 'stdexec::set_value_t'), while the same code works withinline_scheduler.Changes
common.cuh: small helpers for how a result is kept in temp storage. A reference result is stored as a pointer to the referenced object, anything else as a decayed value like before.result_size_foruses the stored size.then,upon_error,upon_stopped: the kernel stores the result through that helper, and the reference is passed on from the stored pointer.cudaStreamSynchronize) before it is passed on, because the address is only known after the kernel has run. Value results don't change. (Discussed onnvexec::then/upon_error/upon_stoppedshould handle callables that return by reference #958.)then'sset_valueconstraint is nowstd::invocable<Fun, Args...>instead ofstd::invocable<Fun, __decay_t<Args>...>, same asupon_error.Tests
New cases in
test/nvexec/then.cpp(int&andconst int&),upon_error.cppandupon_stopped.cpp(int&). Each one writes through or reads from the returned reference in the next step.Tested on a T4 with clang 20 + CUDA 12.9, on top of main 697cd69:
test.nvexecpasses: 128 test cases / 779 assertions, 3 runs