如何在CUDA中定义dim3结构的常量数组

时间:2016-07-10 16:13:20

标签: struct cuda constants static-initialization

我正在写一些CUDA代码在设备上运行。代码将使用两个常量值的查找表。第一个是256个无符号整数的数组,我将其声明为:

__constant__ 
uint16_t edgeTable[256]={
   0x000,
   0x019,
   ... etc.
};

这似乎编译得很好。

第二个是固定大小的dim3数组,我试过这个:

__constant__
dim3 offsets[8] = {
    {0, 0, 0}, {0, 0, 1}, {0, 1, 0},
    ... etc 
};

编译器对象所针对的。错误消息:

error: dynamic initialization is not supported for __device__, __constant__ and __shared__ variables.

也许我误解了动态初始化,但在我看来,这是静态初始化,编译器可以计算出所有值的大小,并提供所有值。

我在这里缺少什么?

我如何实现我的目标?

由于

我在Ubuntu 14.04上使用CUDA7.5工具包和gcc 4.8.4

1 个答案:

答案 0 :(得分:4)

这个问题的重要特征是CUDA使用C ++编译模型,dim3被视为一个类。所以,同时:

dim3 foo = {1,1,1};

在C ++ 11中是合法的,因为参数化构造函数初始化支持,这个:

__constant__ dim3 foo = {1,1,1};

不是,因为这意味着对常量内存对象进行动态初始化,而CUDA执行模型并不允许这样做。

如果常量记忆方面对您很重要并且您希望方便dim3,则可以执行以下操作:

#include <cstdio>

__constant__ int offsets[3*8];

__global__ void kernel()
{
    if (threadIdx.x < 8) {
        dim3 val = *reinterpret_cast<dim3*>(&offsets[3*threadIdx.x]);
        printf("%d (%d,%d,%d)\n", threadIdx.x, val.x, val.y, val.z);
    }
}

void setup_offsets()
{
    // This requires C++11 support
    dim3 ovals[8] = { {0,0,0}, 
                      {1,0,0}, {0,1,0}, {0,0,1},
                      {1,1,0}, {1,0,1}, {0,1,1},
                      {1,1,1} };

    cudaMemcpyToSymbol(offsets, &ovals[0], sizeof(ovals));
}

int main(void)
{
    setup_offsets();
    kernel<<<1,8>>>();
    cudaDeviceSynchronize();
    cudaDeviceReset();
    return 0;
}

这有点黑客,但在这种情况下你可能希望得到的最好。查看该代码的PTX,编译器已正确发出ld.const.u32以获取dim3的每个成员。