如何在 CUDA 中定义 dim3 结构的常量数组
How to define constant arrays of dim3 structs in CUDA
我正在向设备上的 运行 写入一些 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 和 gcc 4.8.4
上使用 CUDA7.5 工具包
这道题的重要特点是CUDA使用C++编译模型,dim3
被当成class处理。所以同时:
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
.
的每个成员
我正在向设备上的 运行 写入一些 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 和 gcc 4.8.4
上使用 CUDA7.5 工具包这道题的重要特点是CUDA使用C++编译模型,dim3
被当成class处理。所以同时:
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
.