4 ms·
> Modern CUDA uses explicit programmer-managed masks, which is powerful and takes advantage of their hardware specifics. But mis-using the mask can cause a dead
by my123 4y ago
> Modern CUDA uses explicit programmer-managed masks, which is powerful and takes advantage of their hardware specifics. But mis-using the mask can cause a deadlock, as divergent threads could simply never participate in a subgroup operation that expects them to, leaving the other threads to block forever. I can see why this solution leaves to be desired, as it just offloads the problem and the risk of misuse to the user.
Note, on Volta (2017, present on customer since Turing in 2018) onwards, Independent Thread Scheduling is present, with a separate instruction pointer per SIMT thread.
This allows to have atomics across different lanes of the same warp, as such providing the guarantees assumed by the C++ memory model. Quite some modern CUDA apps are starting to rely on that, and as such will not work on Pascal or earlier, nevermind other GPU vendors.
Cooperative Groups are very flexible in CUDA too.
https://docs.nvidia.com/cuda/volta-tuning-guide/index.html#sm-independent-thread-scheduling https://docs.nvidia.com/cuda/volta-tuning-guide/index.html#s...
As such, control flow is handled very differently on post-Volta GPUs compared to pre-Volta ones, with pre-Volta more akin to what AMD still does today.
- atq2119 4y agoThe statement about C++ is somewhat misleading. C++ has multiple notions of forward progress of various strength, and post-Volta does not satisfy the one that you'd be used to from CPUs, which is concurrent forward progress. However, it does satisfy parallel forward progress.
- my123 4y agoThe C++ standard encourages, but doesn't require concurrent forward progress. However, a guarantee for forward progress for diverged threads in a warp is provided for Volta.
- g0b 4y agoI'm in fact talking about post-Volta hardware there, but this is not about forward progress, I meant using __ballotsync() and getting it wrong (ie waiting on the __activemask() from outside an if, but only in one branch of the if, meaning some of the threads will never participate in the sync) will deadlock the GPU. It's a powerful (since _different_ locations statically can sync with each other), but also risky abstraction to expose, as compared to GLSL where it's impossible to deadlock anything by using subgroup intrinsics.