You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If the call to cuda::memcpy_async is replaced with
int warp_id = threadIdx.x / 32;
bool elected = warp_id == 0 && elect_sync(~0);
if (elected) {
cuda::ptx::cp_async_bulk(cuda::ptx::space_cluster, cuda::ptx::space_global,
smem_a, a, num_bytes, cuda::device::barrier_native_handle(bar));
cuda::ptx::mbarrier_expect_tx(cuda::ptx::sem_relaxed, cuda::ptx::scope_cta, cuda::ptx::space_shared,
cuda::device::barrier_native_handle(bar), num_bytes);
}
the codegen is much better. So what's wrong with cuda::memcpy_async?
After some investigation I noticed the following problems:
our __cp_async_bulk_shared_global elects with __g.thread_rank() == 0 and not with elect_sync, leading to bad codegen because the compiler does not recognize the uniform data path
inside the bulk copy code path of cuda::memcpy_async, we elect twice (using __g.thread_rank() == 0), once in __cp_async_bulk_shared_global, once for the __memcpy_completion_impl::__defer, both need to elect the same thread, so we cannot use elect_sync. Optimally, this should be in a single if(elected) { ... } containing both the scheduling of the bulk copy and the barrier update
bar.arrive_and_wait() waits for phase completion with backoff (using cuda::std::chrono, timers and thread yielding). Since sm90, we have hardware support (SYNCS) for waiting for a parity change, so we should use that.
I received the following piece of code (shortened) using
cuda::memcpy_asyncand its author claims the codegen is inefficient:Full version here: https://godbolt.org/z/jGz884cE5
If the call to
cuda::memcpy_asyncis replaced withthe codegen is much better. So what's wrong with
cuda::memcpy_async?After some investigation I noticed the following problems:
our
__cp_async_bulk_shared_globalelects with__g.thread_rank() == 0and not withelect_sync, leading to bad codegen because the compiler does not recognize the uniform data pathinside the bulk copy code path of
cuda::memcpy_async, we elect twice (using__g.thread_rank() == 0), once in__cp_async_bulk_shared_global, once for the__memcpy_completion_impl::__defer, both need to elect the same thread, so we cannot useelect_sync. Optimally, this should be in a singleif(elected) { ... }containing both the scheduling of the bulk copy and the barrier updatebar.arrive_and_wait()waits for phase completion with backoff (usingcuda::std::chrono, timers and thread yielding). Since sm90, we have hardware support (SYNCS) for waiting for a parity change, so we should use that.