c - 避免翘曲发散

标签 c cuda gpu-warp

我有 bool 型一维数组 T[N] 控制移位值,如下所示:

**a:指向全局内存中n*n矩阵的指针数组 我想为每个矩阵 a 子结构一个 shift*Identity 以获得:

a=a-shift*eye(n)

我有:

__device__ bool T[N];
__device__ float shift1[N];
__device__ float shift2[N];
__device__ float* a[N];

shift的值由T控制 如果 T[i]==true => shift=shift1 否则 shift=shift2;

int tid=threadIdx.x;

      if(tid < N){

              if(T[tid]){

               for (int i=0;i<n;i++){

                   a[tid][i*n+i]=a[tid][i*n+i]-shift1[tid];
               }

            }
        else {

          for (int i=0;i<n;i++){

                   a[tid][i*n+i]=a[tid][i*n+i]-shift2[tid];
               }
            }
        }
      __syncthreads();

这会导致扭曲发散并降低我的代码速度。是否有避免上述循环的翘曲发散的技巧?

最佳答案

正如@AnastasiyaAsadullayeva 所建议的,我相信对您的代码进行相当简单的转换可能会减少您对 warp divergence 的担忧:

int tid=threadIdx.x;
  float myshift;
  if (T[tid]) myshift = shift1[tid];
  else myshift = shift2[tid];
  if(tid < N){
           for (int i=0;i<n;i++){

               a[tid][i*n+i]=a[tid][i*n+i]-myshift;
           }

        }
  __syncthreads();

编译器将预测 myshift 的加载(创建已经提到的“条件加载”)。这种预测最小化了负载本身的发散成本。此转换下的其余代码是非发散的(tid >= N 除外,这应该无关紧要)。

同样,如前所述,整个转换可能已经被编译器观察到并完成了。这是可能的,但如果不运行您未提供的实际完整测试用例,则无法确认。

更好的方法是以您认为自然的方式编写代码,然后让编译器处理它。在这一点上,您可以使用分析器和分析驱动的优化来确定扭曲发散是否实际上是您代码中的性能问题(分析器有指标和其他方法来评估扭曲发散并在您的代码中指示其严重性。)

关于c - 避免翘曲发散,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32563604/

相关文章:

python - 不能创建超过 10 个 mqueue

c++ - 如何正确地将 cuda 头文件与设备功能链接起来?

cuda - 有效载荷中的 Optix 动态大小数组

cuda - 在 CUDA 9 中附加了一些以 `_sync()` 命名的内在函数;语义相同?

c - BST 树到 AVL

c - 如何在 C 中验证 X509 证书

cuda - __match_any_sync 在计算能力 6 上的替代方案是什么?

cuda - 如何执行 shfl.idx 的相反操作(即扭曲分散而不是扭曲聚集)?

c - printf 只取最后一次 scanf

c++ - 使用自定义内核或 CUBLAS 对 vector 张量积进行 CUDA 优化