【问题标题】:CUDA summation reduction puzzleCUDA 求和归约之谜
【发布时间】:2013-04-07 14:54:16
【问题描述】:

CUDA 的减少让我完全感到困惑!首先,Mark Harris 的 this 教程和 Mike Giles 的 this one 都使用了声明 extern __shared__ temp[]。声明时在 C 中使用关键字 extern,但分配发生在“elsehre”(例如,通常在另一个 C 文件上下文中)。 extern 这里的相关性是什么?我们为什么不使用:

__shared__ float temp[N/2];

例如?或者我们为什么不将temp 声明为全局变量,例如

#define N 1024
__shared__ float temp[N/2];

__global__ void sum(float *sum,  float *data){ ... }

int main(){
 ...
 sum<<<M,L>>>(sum, data);
}

我还有一个问题?每个块应该使用多少块和线程来调用求和内核?我试过this example(基于this)。

注意:您可以找到有关我的设备的信息here

【问题讨论】:

  • 有两种不同的共享内存分配方法,一种是静态分配的大小,一种是动态分配的大小。阅读here。如果你说__shared__ float temp[256]; 你正在做一个静态分配。如果您说extern __shared__ float temp[];,您正在执行动态(在运行时)分配。

标签: cuda gpu gpgpu nvidia


【解决方案1】:

第一个问题的答案是 CUDA 在运行时支持动态共享内存分配(请参阅this SO question 和the documentation 了解更多详细信息)。使用extern 声明共享内存向编译器表明共享内存大小将在内核启动时确定,以字节作为参数传递给&lt;&lt;&lt; &gt;&gt;&gt; 语法(或等效地通过API 函数),类似于:

sum<<< gridsize, blocksize, sharedmem_size >>>(....);

第二个问题通常是启动将完全填满 GPU 上所有流式多处理器的块数。大多数明智地编写的缩减内核将在每个线程中累积许多值,然后执行共享内存缩减。减少要求每个块的线程数是 2 的幂:这通常为您提供 32、64、128、256、512(如果您有 Fermi 或 Kepler GPU,则为 1024)。这是一个非常有限的搜索空间,只需进行基准测试,看看什么在您的硬件上最有效。您可以在herehere 找到有关块和网格大小的更一般性的讨论。

【讨论】:

  • 如果我不指出我发布的答案中的所有内容要么在文档中,要么可以通过阅读 SO CUDA 常见问题或使用搜索引擎找到,这也是我的疏忽你的选择....
  • 谢谢,主要问题确实是我必须指定应该分配的共享内存的大小。其次,这个函数,正如它所写的那样,返回一个包含每个块部分和的数组,这些部分和应该最后相加。我最终将不得不修改一些代码......
猜你喜欢
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-17
  • 2019-03-24
  • 2017-09-14
  • 2014-12-03
相关资源
最近更新 更多