喂 我在网站上看过这个示例内核
__global__ void loop1( int N, float alpha, float* x, float* y ) {
int i;
int i0 = blockIdx.x*blockDim.x + threadIdx.x;
for(i=i0;i<N;i+=blockDim.x*gridDim.x) {
y[i] = alpha*x[i] + y[i];
}
}
在C
中计算此功能 for(i=0;i<N;i++) {
y[i] = alpha*x[i] + y[i];
}
当然内核中的for循环不是必需的吗?你可以y[i0] = alpha*x[i0] + y[i0]
完全删除for循环。
我只是好奇为什么它在那里以及它的目的是什么。这假定是内核调用,例如loop1<<<64,256>>>>
,因此可能是gridDim.x = 1
答案 0 :(得分:4)
如果向量的条目多于启动的线程,则需要内核中的for循环。如果可能的话,启动足够的线程当然更有效。
答案 1 :(得分:2)
有趣的内核。内核中的循环是必要的,因为N大于总线程数,即16 384(blockDim.x * gridDim.x),但我认为这样做不是好习惯( CUDA的重点是使用SIMT概念)。根据CUDA编程指南,一个内核最多可以包含65535个线程块。此外,从Compute Capability 2.x(Fermi)开始,每个块最多可包含1024个线程(Fermi之前为512个)。您也可以(如果可能)将代码分成多个(顺序)内核。
答案 2 :(得分:1)
就像我们想要相信CUDA GPU具有无限的执行资源一样,他们却没有,并且高度优化的代码的作者发现展开的for循环(通常具有固定数量的块)可以提供最佳性能。编码很痛苦,但优化的CPU代码也很痛苦。
btw一位评论者提到这段代码会产生合并问题,我不明白为什么。如果基址正确对齐(64B,因为它们是浮点数),则此代码的所有内存事务都将被合并,前提是线程/块也可以被64整除。