C++ CUDA错误:“;“设备”、“常量”和“共享变量”不支持动态初始化;

C++ CUDA错误:“;“设备”、“常量”和“共享变量”不支持动态初始化;,c++,memory-management,cuda,gpu,variable-initialization,C++,Memory Management,Cuda,Gpu,Variable Initialization,我试图静态初始化GPU内存中的只读std::map变量,如下所示: // EXAMPLE 1: using namespace std; // first attempt: __device__ extern const __device__ extern const map<char, const char*> BYTES_TO_WORDS = { {0xB0, "zero"}, {0xB1, "one"}, {0xB2, "two"}, {0xB3, "three"}}; /

我试图静态初始化GPU内存中的只读
std::map
变量,如下所示:

// EXAMPLE 1:
using namespace std;

// first attempt: __device__ extern const
__device__ extern const map<char, const char*> BYTES_TO_WORDS = {
{0xB0, "zero"}, {0xB1, "one"}, {0xB2, "two"}, {0xB3, "three"}};

// second attempt: __const__ static
enum class Color{RED, GREEN, BLUE};
enum class Device{PC, TABLET, PHONE};

__constant__ static map<Color, Device> COLORS_TO_THINGS = {
{Color::RED,Device::PC},{Color::GREEN,Device::TABLET},{Color::BLUE,Device::PHONE}};
我只想能够创建和初始化一个只读的
std::map
,并从CPU和GPU代码访问它。如果你能告诉我怎么做,我将不胜感激

编辑:
有人指出,设备代码中不支持标准库。但是,我得到的错误似乎表明这是内存管理问题。

< P>初始化C++对象,如<代码> STD::MAP< /Cord>涉及在运行时调用构造函数。用于初始化
std::map
s的C++11语法是一种调用
std::initializer\u list
重载
std::map
构造函数的形式。您使用
PLAIN_ARRAY
的示例不调用任何构造函数,因为这是一种仅涉及按值初始化某些
int
s的形式,初始化
int
不需要构造函数调用

在CUDA中,不可能对存储在GPU上的全局变量使用任何类型的动态初始化,例如
\uuuuu device\uuuuuu
\uuuu constant\uuuuu
变量,这意味着对象的初始值必须在编译时已知,而不仅仅是在调用构造函数后在运行时生成

另一个问题是,即使在设备代码中可以调用构造函数的上下文中,也不能调用“代码> STD::MAP< /COD>的构造函数,因为它是C++标准库的一部分,它没有< Cuth>因此,它只能从主机代码中使用。CUDA运行时不定义C++ STL类的任何类型的设备功能。即使您设法将

cudaMemcpy()
一个
std::map
从主机内存映射到GPU内存,您也无法使用该对象,首先是因为它的所有成员函数都是
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu主机
函数,没有对应的
,其次,
std::map
将在内部包含指向动态分配的主机内存的指针成员变量,该内存将不是GPU上的有效内存地址

另一种方法是使用结构的普通数组而不是映射,例如:

__device__
const struct {
    unsigned char byte;
    const char word[10];
} BYTES_TO_WORDS[] = {
    {0xB0, "zero"},
    {0xB1, "one"},
    {0xB2, "two"},
    {0xB3, "three"}
};
但是,与使用
std::map
不同,您必须实现通过其键手动查找值


我只想能够创建和初始化只读
std::map
,并从CPU和GPU代码访问它

不幸的是,这并不简单,因为您不能将变量同时定义为
\uuuu设备\uuuu
\uuu主机\uuuu
。要从主机代码访问
\uuuu设备\uuuu
变量,必须使用
cudamemcpyfromsymsymbol()
,这与只访问普通变量相比非常尴尬。因此,您可能最终不得不在主机内存中定义常量,然后将常量从主机内存复制到设备内存:

const byte_word BYTES_TO_WORDS[] = {
    {0xB0, "zero"},
    // ...
};

// uninitialized array
__device__
byte_word DEV_BYTES_TO_WORDS[sizeof BYTES_TO_WORDS / sizeof(byte_word)];

// at startup, use `cudaMemCpyToSymbol()` to populate `DEV_BYTES_TO_WORDS`
// from `BYTES_TO_WORDS`.

另一种方法是使用预处理器define在两个数组之间有效地复制和粘贴相同的初始值设定项,而不是在运行时复制数据。在任何情况下,都需要两个单独的阵列。

std::map
无法从GPU代码中正确使用,即使您可以解决此存储问题。限制已经确定。谢谢,我没有意识到。错误很明显。
普通数组
字节到单词
的初始化过程不同,因为一个是静态的,另一个是动态的,并且涉及运行构造函数,这对于静态声明的设备符号是非法的
const byte_word BYTES_TO_WORDS[] = {
    {0xB0, "zero"},
    // ...
};

// uninitialized array
__device__
byte_word DEV_BYTES_TO_WORDS[sizeof BYTES_TO_WORDS / sizeof(byte_word)];

// at startup, use `cudaMemCpyToSymbol()` to populate `DEV_BYTES_TO_WORDS`
// from `BYTES_TO_WORDS`.