我正在写一些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
答案 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
的每个成员。