我是cuda的初学者,我遇到了一些困难
如果我有一个大小为N的输入向量A和结果向量B,并且B [i]依赖于除A [i]之外的A的所有元素,我怎么能编码它而不必多次调用内核在一个串口for循环?我想不出一种同时兼顾外圈和内圈的方法。
编辑:拥有cc 2.0的设备
示例:
// a = some stuff
int i;
int j;
double result = 0;
for(i=0; i<1000; i++) {
double ai = a[i];
for(j=0; j<1000; j++) {
double aj = a[j];
if (i == j)
continue;
result += ai - aj;
}
}
我现在有这个:
//in host
int i;
for(i=0; i<1000; i++) {
kernelFunc <<<2, 500>>> (i, d_a)
}
有没有办法消除串行循环?
答案 0 :(得分:2)
这样的事情应该有用,我想:
__global__ void my_diffs(const double *a, double *b, const length){
unsigned idx = threadIdx.x + blockDim.x*blockIdx.x;
if (idx < length){
double my_a = a[idx];
double result = 0.0;
for (int j=0; j<length; j++)
result += my_a - a[j];
b[idx] = result;
}
}
(用浏览器编写,未经测试)
这可以通过几种方式进一步优化,但对于具有L1缓存的cc 2.0和更新设备,这些优化的好处可能很小:
double
个元素?)因此可能会受到限制j
索引)。同样,对于cc 2.0和更新的设备,由于L1缓存以及广播warp全局读取的能力,这可能没有多大帮助。如果你必须使用cc 1.x设备,那么你将获得一次或多次优化的重要意义 - 在这种情况下,我在这里显示的代码将明显变慢。
请注意,我选择不打扰我们从其自身减去a[i]
的特殊情况,因为它应该大约为零,并且不应该打扰您的结果。如果您对此感到担忧,可以轻松地将其解决。
如果你增加块并减少每个块的线程,你也会获得更多性能,可能是这样的:
my_diffs<<<8,128>>>(d_a, d_b, len);
原因是许多GPU有超过1或2个SM。为了最大化这些具有如此小数据集的GPU的性能,我们希望尝试在每个SM上启动至少一个块。在网格中有更多的块使这更有可能。
如果你想完全并行计算,那么方法是在GPU内存中创建一个二维矩阵(让我们称之为c [...]),方形尺寸等于长度你的矢量。然后我会创建一个2D线程网格,并让每个线程执行减法(a[row] - a[col]
)并将其结果存储在c[row*len+col]
中。然后,我将启动第二个(1D)内核来对c
的列进行求和(每个线程都有一个循环来对一列求和)以创建结果向量b
。但是我不确定这会比我概述的方法更快。这种“更完全并行化”的方法也不会轻易适应我所讨论的优化。