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

Struct 如何在CUDA中定义dim3结构的常量数组,struct,cuda,constants,static-initialization,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}, ... et

我正在编写一些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的CUAD7.5工具包,GCC 4.84/P>< P>这个问题的重要特征是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 C.U32来获取DIM3的每个成员。

< P>这个问题的重要特征是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 C.U32来获取DIM3../P>的每个成员可能是愚蠢的问题——你是否通过了标志使C++ 11?参数化构造函数初始化DIM3是C++之前不支持C++的类,也许你的问题的答案是这实际上是一种动态初始化的形式。这些变量类型不支持上述和动态初始化,正如编译器所指出的,无论c++11编译器开关如何。作为一种可能的解决方法,您可以创建一个int数组,静态初始化为_uconstant _uuint,然后将其转换为内核代码中的dim3数组,可能类似于。我想你自己可能已经找到了这样的解决方法,所以,我不是说这是一个答案!谢谢我确实通过了-std=c++11,但是完全没有考虑到结构是一个类,因此当然会被动态初始化这一事实。我想,Robert Crovella,你的答案是我唯一能做的…可能是愚蠢的问题——你是否通过了标志使C++ 11?参数化构造函数初始化DIM3是C++之前不支持C++的类,也许你的问题的答案是这实际上是一种动态初始化的形式。这些变量类型不支持初始化,正如编译器所指出的,无论c++11编译器开关如何。作为一种可能的解决方法,您可以创建一个int数组,静态初始化为_uconstant _uuint,然后将其转换为内核代码中的dim3数组,可能类似于。我想你自己可能已经找到了这样的解决方法,所以,我不是说这是一个答案!谢谢我确实通过了-std=c++11,但是完全没有考虑到结构是一个类,因此当然会被动态初始化这一事实。我想@Robert Crovella你的回答是我唯一能做的。。