假设我们具有以下代码:
while (condition) {
...
for (uint32_t gap = x >> 1; gap > 0; gap >>= 1) {
val += __shfl_down_sync(mask, val, gap);
}
if (warpLane == 0)
atomicAdd(&global_memory[threadIdx.x], val);
...
}
在这种情况下,如果线程束中的线程按以下顺序进入while循环:
全部32个线程,全部32个线程,只有16个线程。
如何获取参与while循环语句的线程掩码?
根据https://devblogs.nvidia.com/using-cuda-warp-level-primitives中所述的指南,以下代码可能导致未定义的行为:
while (condition) {
uint32_t active = __activemask();
for (uint32_t gap = x >> 1; gap > 0; gap >>= 1) {
val += __shfl_down_sync(active, val, gap);
}
if (warpLane == 0)
atomicAdd(&global_memory[threadIdx.x], val);
...
}
根据指南,__ activemask()可能不会如我所愿生成掩码。
以下根据上述指南也会导致未定义的行为:
while (condition) {
uint32_t active = __activemask();
for (uint32_t gap = x >> 1; gap > 0; gap >>= 1) {
val += __shfl_down_sync(active, val, gap);
}
if (warpLane == 0)
atomicAdd(&global_memory[threadIdx.x], val);
...
__warpsync(active);
}
然后,如何正确获得口罩?
答案 0 :(得分:1)
您可以像这样使用cooperative groups:
<Select className="abc" classNamePrefix="react-select" ... />
如果要自己生成蒙版并过时,可以使用:
#include <cooperative_groups.h>
namespace cg = cooperative_groups;
while (condition) {
...
auto active = cg::coalesced_threads(); // this line can be moved out of while if the condition does not cause thread divergence
for (uint32_t gap = x >> 1; gap > 0; gap >>= 1) {
//val += __shfl_down_sync(mask, val, gap);
val += active.shfl_down(val, gap);
}
if (warpLane == 0)
atomicAdd(&global_memory[threadIdx.x], val);
...
}
但是,如果您在代码中进一步分支,则必须在分支之前始终跟踪uint32_t FullMask = 0xFFFFFFFF;
uint32_t mask = __ballot_sync(FullMask, someCondition);
并使用它而不是mask
中的FullMask
。因此,分支之前的第二次更新将是:
ballot