我的情况:warp 中的每个线程都在其自己完全独立且不同的数据数组上运行。所有线程循环遍历它们的数据数组。每个线程的循环迭代次数不同。(这会产生成本,我知道)。
在for循环中,每个线程需要计算三个浮点数后保存最大值。在for循环之后,warp中的线程将通过检查仅由它们在warp中的“相邻线程”计算的最大值(由奇偶校验确定)来“通信”。
问题:
- 如果我通过乘法避免“最大”操作中的条件,这将避免扭曲发散,对吗?(见下面的示例代码)
- (1.) 中提到的额外乘法运算是值得的,对吧?- 即比任何形式的经线发散都要快得多。
- 导致 warp 发散的相同机制(所有线程的一组指令)可以在 for 循环结束时作为隐式“线程屏障”(对于warp )被利用(与“#pragma omp for" 非 GPU 计算中的语句)。因此,在一个线程检查另一个线程保存的值之前,我不需要在 for 循环之后对扭曲进行“syncthreads”调用,对吗?(这是因为“synthreads”仅适用于“整个 GPU”,即 inter-warp 和 inter-MP,对吧?)
示例代码:
__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 上实施我的算法之前,我正在研究算法的各个方面,以确保它值得实施。所以请多多包涵。。