分配共享内存

时间:2011-04-03 17:34:42

标签: c++ c cuda gpu-shared-memory

我试图通过使用常量参数来分配共享内存,但是收到错误。我的内核看起来像这样:

__global__ void Kernel(const int count)
{
    __shared__ int a[count];
}

我收到错误

  

错误:表达式必须具有常量值

计数是常量!为什么我收到此错误?我怎么能解决这个问题?

5 个答案:

答案 0 :(得分:83)

CUDA支持动态共享内存分配。如果你像这样声明内核:

__global__ void Kernel(const int count)
{
    extern __shared__ int a[];
}

然后传递所需的字节数作为内核启动的第三个参数

Kernel<<< gridDim, blockDim, a_size >>>(count)

然后可以在运行时调整大小。请注意,运行时仅支持每个块的单个动态声明分配。如果需要更多,则需要在单个分配中使用指向偏移的指针。使用指针时,请注意共享内存使用32位字,并且所有分配必须是32位字对齐,而不管共享内存分配的类型。

答案 1 :(得分:34)

const并不代表“常数”,它意味着“只读”。

常量表达式是编译器在编译时知道其值。

答案 2 :(得分:20)

选项一:声明具有常量值的共享内存(与const不同)

__global__ void Kernel(int count_a, int count_b)
{
    __shared__ int a[100];
    __shared__ int b[4];
}

选项二:在内核启动配置中动态声明共享内存:

__global__ void Kernel(int count_a, int count_b)
{
    extern __shared__ int *shared;
    int *a = &shared[0]; //a is manually set at the beginning of shared
    int *b = &shared[count_a]; //b is manually set at the end of a
}

sharedMemory = count_a*size(int) + size_b*size(int);
Kernel <<<numBlocks, threadsPerBlock, sharedMemory>>> (count_a, count_b);

注意:给定相同地址的动态共享内存指针全部。我使用两个共享内存数组来说明如何在共享内存中手动设置两个数组。

答案 3 :(得分:3)

来自“CUDA C编程指南”:

通过插入以下形式的表达式来指定执行配置:

<<<Dg, Db, Ns, S>>>

其中:

  • Dg 的类型为 dim3 ,并指定网格的尺寸和尺寸......
  • Db 的类型为 dim3 ,并指定每个块的尺寸和大小......
  • Ns 的类型为 size_t ,并指定共享内存中的字节数,除了此调用之外,还为每个块动态分配静态分配的内存。这个动态分配的内存被声明为外部数组的任何变量使用,如 __ shared __ 中所述; Ns是可选参数,默认为0;
  • S的类型为 cudaStream_t ,并指定关联的流...

因此,通过使用动态参数Ns,用户可以指定一个内核函数可以使用的共享内存的总大小,无论该内核中有多少共享变量。

答案 4 :(得分:1)

你不能像这样声明共享变量..

__shared__ int a[count];

虽然如果你对数组a的最大大小足够肯定,那么你可以直接声明像

__shared__ int a[100];

但是在这种情况下你应该担心你的程序中有多少个块,因为将共享内存固定到一个块(而不是被完全利用)会导致你使用全局内存进行上下文切换(高延迟),因此表现不佳......

声明

这个问题有一个很好的解决方案
extern __shared__ int a[];

并在从内存调用内核时分配内存,如

Kernel<<< gridDim, blockDim, a_size >>>(count)

但你也应该在这里烦恼,因为如果你在块中使用的内存比在内核中分配的内存多,那么你将会得到意想不到的结果。