Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CUDA-这个循环在做什么_Cuda - Fatal编程技术网

CUDA-这个循环在做什么

CUDA-这个循环在做什么,cuda,Cuda,哎 我在一个网站上看到了这个内核示例 __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]; } } \uuuu全局\uuuuu无

哎 我在一个网站上看到了这个内核示例

 __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];
    }
}   
\uuuu全局\uuuuu无效循环1(整数N、浮点alpha、浮点*x、浮点*y){
int i;
int i0=blockIdx.x*blockDim.x+threadIdx.x;

对于(i=i0;i
因此,假设
gridDim.x=1

如果向量的入口比已启动的线程多,则需要内核中的for循环。如果可能,启动足够多的线程当然更有效。

有趣的内核。内核中的循环是必要的,因为N大于线程总数,这是16384(blockDim.x*gridDim.x),但我认为这样做不是好的做法(CUDA的全部要点是使用SIMT概念)。根据CUDA编程指南,一个内核最多可以有65535个线程块。此外,从Compute Capability 2.x(费米)开始每个块最多可以有1024个线程(费米之前为512个),也可以(如果可能)将代码分成多个(顺序的)内核。

尽管我们相信CUDA GPU有无限的执行资源,但它们没有,而且高度优化代码的作者发现,通常具有固定块数的循环展开可以提供最佳性能。这会导致痛苦的编码,但优化的CPU代码也相当痛苦


顺便说一句,一位评论员提到这段代码会有合并问题,我不明白为什么。如果基址正确对齐(64B,因为它们是浮点数),如果线程/块也可以被64整除,则此代码的所有内存事务都将合并。

啊,我明白了,所以在这种情况下,如果N大于64*256,则需要合并。非常感谢实际使用这样的内核执行配置>gridDim。x值是64,而不是1,因为gridDim内置在dim3变量中包含维度of网格和该网格有64个使用一维的线程块。有时,最好有一个易于展开的for循环(在本例中是这样),而不是启动太多的块并不断切换它们。可以根据经验为给定问题找到最佳数量。@Pavan ok,但我认为这也是(全局的)内存访问可以在for循环中优化。在上面的示例中,y[i]=alpha*x[i]+y[i];迭代非常分散(i0,i0+numberOfThreads,i0+2*numberOfThreads,…)。Szepetkowski,你是对的。我通常使用for循环访问连续的数据块,所以我从来没有这样想过:)
   for(i=0;i<N;i++) {
      y[i] = alpha*x[i] + y[i];
   }