【发布时间】:2021-06-10 05:10:15
【问题描述】:
我对 CUDA 编程比较陌生,所以我想澄清当我将结构传递到内核时的行为。我定义了以下struct 来在某种程度上模仿知道自己大小的 3D 数组的行为:
struct protoarray {
size_t dim1;
size_t dim2;
size_t dim3;
float* data;
};
我创建了两个protoarray类型的变量,在主机端和设备端通过malloc和cudaMalloc为数据动态分配空间,并更新dim1、dim2和dim3以反映我想要的数组大小这个结构来表示。我在this thread 中读到struct 应该通过副本传递。所以这就是我在内核中所做的事情
__global__ void kernel(curandState_t *state, protoarray arr_device){
const size_t dim1 = arr_device.dim1;
const size_t dim2 = arr_device.dim2;
for(size_t j(0); j < dim2; j++){
for(size_t i(0); i < dim1; i++){
// Do something
}
}
}
结构体是通过拷贝传递的,所以它的所有内容都被拷贝到每个块的共享内存中。这是我得到奇怪行为的地方,我希望你能帮助我。假设我在主机端设置了arr_device.dim1 = 2。在内核内部调试并在for 循环之一处设置断点时,检查arr_device.dim1 的值会产生类似16776576 的东西,没有大到足以导致溢出的地方,但这个值正确复制到dim1 中作为@ 987654336@,这意味着for 循环按照我的预期执行。作为一个附带问题,使用size_t 这是必不可少的unsigned long long int 不好的做法,因为GPU 是由32 位内核组成的?
一般来说,将struct 和class 作为参数传递到内核中有多安全,是否应该不惜一切代价避免这种不好的做法?我想将指向类的指针传递给内核是很困难的,因为它们包含指向动态分配内存的成员,并且如果我想通过值传递它们,它们应该非常轻量级。
【问题讨论】:
-
您确定
size_t在 CPU 和 GPU 上的大小相同吗? (我相信,没有构造函数的structs 通常是安全的。) -
@KenY-N:CUDA 保证
sizof(size_t)和sizeof(void *)在 GPU 和设备上是相同的无论使用什么平台。不同平台可能不一样 -
这让我很担心——“结构是通过副本传递的,所以它的所有内容都被复制到每个块的共享内存中”。这根本不是事情的运作方式。无论问题是什么,它都不是由您在此问题中显示的任何内容引起的。 minimal reproducible example,请
-
@KenY-N 全部更改为
unsigned int,现在值匹配。您能否请我参考一些关于struct与内核中的构造函数的问题的来源? @talonmies ““结构是通过副本传递的,因此它的所有内容都被复制到每个块的共享内存中”这基本上是来自我链接的 NVIDIA 开发者论坛线程的引用。 -
@SlavaK.: 好的,在 2009 年确实如此。自 2010 年以来就不是这样了。所有内核参数都放在所有 CUDA 硬件上的专用常量内存库中,除了第一代 G80/ G90 零件