GPU for loops:避免扭曲发散&隐式同义词

时间:2013-02-19 17:06:14

标签: c++ c cuda gpu gpgpu

我的情况:warp中的每个线程都是独立运行的。不同的数据阵列。所有线程都在其数据数组上循环。每个线程的循环迭代次数不同。 (这会产生费用,我知道。)

在for循环中,每个线程在计算三个浮点数后需要保存最大值。在for循环之后,warp中的线程将通过检查由 warp 中的“相邻线程”计算的最大值来“通信”(由奇偶校验确定)。

问题:

  1. 如果我通过乘法避免“max”操作中的条件,这将避免扭曲发散,对吧? (参见下面的示例代码)
  2. (1。)中提到的额外乘法运算是值得的,对吧? - 比任何类型的扭曲分歧都要快得多。
  3. 导致warp散布的相同机制(所有线程的一组指令)可以在for循环结束时被用作隐式“线程障碍”(对于 warp )(与非gpu计算中的“#pragma omp for”语句非常相似。因此,在一个线程检查另一个线程保存的值之前,我不需要在for循环之后对 warp 进行“syncthreads”调用,对吗? (这是因为“synthreads”仅适用于“整个GPU”,即inter-warp和inter-MP,对吗?)
  4. 示例代码:

    __shared__ int N_per_data;  // loaded from host
    __shared__ float ** data;  //loaded from host
    data = new float*[num_threads_in_warp];
    for (int j = 0; j < num_threads_in_warp; ++j)
         data[j] = new float[N_per_data[j]];
    
    // the values of jagged matrix "data" are loaded from host.
    
    
    __shared__  float **max_data = new float*[num_threads_in_warp];
    for (int j = 0; j < num_threads_in_warp; ++j)
         max_data[j] = new float[N_per_data[j]];
    
    for (uint j = 0; j <  N_per_data[threadIdx.x]; ++j)
    {
       const float a = f(data[threadIdx.x][j]);
       const float b = g(data[threadIdx.x][j]);
       const float c = h(data[threadIdx.x][j]);
    
      const int cond_a = (a > b)  &&  (a > c);
      const int cond_b = (b > a)  && (b > c);
      const int cond_c = (c > a)  && (c > b);
    
      // avoid if-statements.  question (1) and (2)
      max_data[threadIdx.x][j] =   conda_a * a  +  cond_b * b  +  cond_c * c; 
    }
    
    
    
     // Question (3):
    // No "syncthreads"  necessary in next line:
    
    // access data of your mate at some magic positions (assume it exists):
    float my_neighbors_max_at_7 = max_data[threadIdx.x + pow(-1,(threadIdx.x % 2) == 1) ][7]; 
    

    在GPU上实现我的算法之前,我正在研究算法的各个方面,以确保它值得实施。所以请耐心等待..

1 个答案:

答案 0 :(得分:1)

  1. 我的猜测是否定的 - 取决于你如何用ifs写出另一个版本。
    编译器可能会使用谓词来屏蔽不需要的写入,在这种情况下,不会有真正的线程发散,只有少数执行但被屏蔽的写入指令。
    你应该让编译器做到这一点,然后比较两个版本的反编译代码,以确定什么是更好的解决方案。
    在您计算有符号整数的最大值的特定情况下,d = a&gt; b? a:b转换为一个PTX ISA指令max.s32所以实际上没有必要像你那样复杂...只需将最大值计算为一个临时变量并进行一次无条件写入。
  2. 是的,但是合成线屏障是一个块内屏障,不是块间屏障,当然也不是插入屏障。