【问题标题】:CUDA Where To Declare Constant For Shared Memory AllocationCUDA 在哪里声明共享内存分配的常量
【发布时间】:2017-05-14 07:38:58
【问题描述】:

我正在为 1024 个矩阵运行适应度函数,每个矩阵都有自己的块并且大小相同。每个块都有n*n 线程(矩阵的维度)并且需要有n*n 共享内存,这样我就可以轻松地进行求和。但是,所有矩阵的维度n 在运行前是可变的(即可以手动更改,尽管始终是 2 的幂,所以求和很简单)。这里的问题是必须使用常量分配共享内存,但我还需要将值从主机传递给内核。我在哪里声明维度n,以便它对 CPU 可见(用于传递给内核)并且可用于声明共享内存的大小(在内核内)?

我的代码结构如下:

来自main.cu我调用内核:

const int num_states = 1024
const int dimension = 4

fitness <<< num_states, dimension * dimension >>> (device_array_of_states, dimension, num_states, device_fitness_return);

然后在kernel.cu 我有:

__global__ void fitness(
    int *numbers, 
    int dimension, 
    int num_states, 
    int *fitness_return) {
    __shared__ int fitness[16]; <<-- needs to be dimension * dimension
    //code
}

numbers 是一个表示 1024 个矩阵的数组,dimension 是行列长度,num_states 是 1024,fitness_return 是一个长度为 1024 的数组,用于保存每个矩阵的适应度值。在内核中,共享内存是用dimension 的平方硬编码的(所以在这个例子中dimension 是4)。

我在哪里以及如何声明dimension,以便它可以用于分配共享内存以及调用内核,这样我只需在一个地方更新dimension?感谢您的帮助。

【问题讨论】:

  • 编辑了我的答案。
  • 在使用之前在全局范围内声明它。
  • 模板参数在这种情况下是你的朋友

标签: cuda constants declaration gpu-shared-memory


【解决方案1】:

分配的共享内存量在所有块上是统一的。您可能在每个块中使用不同数量的共享内存,但它仍然可用。此外,无论如何共享内存的数量都相当有限,因此 n*n 元素不能超过maximum amount of space(通常为 48KiB);对于float-type 元素(每个 4 字节),这意味着 n

现在,有两种分配共享内存的方法:静态和动态。

静态分配是您作为示例给出的,这是行不通的:

__shared__ int fitness[16];

在这些情况下,大小必须在编译时知道(在设备端代码编译时)——这对你来说不是这样。

使用动态共享内存分配,您在内核代码中指定大小 - 您在leave it empty 和前面加上extern

extern __shared__ int fitness[];

相反,你在启动内核时指定数量,不同块的线程不一定知道它是什么。

但在您的情况下,线程 确实 需要知道 n 是什么。好吧,只需将其作为内核参数传递即可。所以,

__global__ void fitness(
    int *numbers, 
    int dimension, 
    int num_states, 
    int *fitness_return,
    unsigned short fitness_matrix_order /* that's your n*/) 
{
    extern __shared__ int fitness[];
    /* ... etc ... */
}

nVIDIA 的Parallel-for-all 博客有a nice post 更深入地介绍了使用共享内存,具体包括静态和动态共享内存分配。

【讨论】:

  • 我想我可能弄错了我的问题。 n 的值在所有块中都是相同的。
  • 如果我没有声明共享内存的大小fitness 我得到错误MSB3721
  • @xjtc55:我不确定这意味着什么,它看起来像是一个 MSVC 错误(我不使用它)。此外,您还没有给出触发此错误的(最小)程序 - 我认为这将是一个单独的问题。
  • @xjtc55:可以重试吗?我插入了一个缺失的 extern 声明。
  • 记住第三个内核启动参数是以字节为单位的动态共享内存的大小,而不是元素的数量。另请注意,每个内核只能有一个 extern __shared__ 数组(任何额外的动态大小的共享内存数组都将分配给相同的内存)。如需更具体的建议,您需要显示完整的实际代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
  • 2012-04-02
相关资源
最近更新 更多