如何在CUDA中的条件while语句中同步warp中的线程?

时间:2019-08-29 11:25:02

标签: cuda

假设我们具有以下代码:

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);
}

然后,如何正确获得口罩?

1 个答案:

答案 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
相关问题