Class 将struct作为参数传递给CUDA内核的行为

Class 将struct作为参数传递给CUDA内核的行为,class,struct,cuda,Class,Struct,Cuda,我对CUDA编程比较陌生,所以我想澄清在将结构传递到内核时结构的行为。我定义了以下struct,在某种程度上模拟了知道自身大小的3D阵列的行为: struct protoarray { size_t dim1; size_t dim2; size_t dim3; float* data; }; 我创建了两个类型为protoarray的变量,在主机和设备端通过malloc和cudamaloc动态地为数据分配空间,并更新dim1、dim2和dim3,以反映我希望此结

我对CUDA编程比较陌生,所以我想澄清在将结构传递到内核时结构的行为。我定义了以下
struct
,在某种程度上模拟了知道自身大小的3D阵列的行为:

struct protoarray {
    size_t dim1;
    size_t dim2;
    size_t dim3;
    float* data;
};
我创建了两个类型为
protoarray
的变量,在主机和设备端通过malloc和cudamaloc动态地为数据分配空间,并更新
dim1
dim2
dim3
,以反映我希望此结构表示的数组大小。我读到,
struct
应该通过copy传递。这就是我在内核中所做的

__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 
        }
    }
}
\uuuuu全局\uuuuuu无效内核(curandState\u t*state,protoarray arr\u设备){
const size_t dim1=arr_device.dim1;
const size_t dim2=arr_device.dim2;
对于(尺寸j(0);j
该结构通过copy传递,因此它的所有内容都复制到每个块的共享内存中。这就是我奇怪行为的地方,我希望你能帮我。假设我在主机端设置了
arr\u device.dim1=2
。在内核内部调试并在
循环的
之一处设置断点时,检查
arr_device.dim1
的值会产生类似
16776576
的结果,其大小不足以导致溢出,但该值会像
2
一样正确复制到
dim1
,这意味着
for
循环按照我的预期执行。作为一个附带问题,使用
size\u t
这一基本
unsigned long long int
的做法是否不好,因为GPU是由32位内核组成的


一般来说,将
struct
class
作为参数传递到内核中有多安全,是应该不惜一切代价避免的坏做法?我认为,如果类包含指向动态分配内存的成员,那么将指向类的指针传递给内核是很困难的,如果我想通过值传递它们,那么它们应该是非常轻量级的。

这是一个部分答案,因为没有,很难/不可能猜测为什么在
arr\u设备.dim1
中会看到无效值

该结构通过copy传递,因此它的所有内容都复制到每个块的共享内存中

不正确。内核参数存储在恒定内存中,该内存是设备全局的,而不是块特定的。它们不是存储在共享内存中(特定于块)

当线程运行时,它通常将参数从常量内存读入寄存器(同样,不是共享内存)

通常,将结构和类作为参数传递到内核中有多安全

我个人的经验法则是:如果结构/类

  • 是微不足道的可复制;及
  • 它的结构/类的所有成员都是为主机和设备端定义的,或者至少在设计时考虑了GPU的使用
然后,传递给内核应该是安全的

将结构和类作为参数传递到内核[-]是否应该不惜一切代价避免这种做法

。但是请记住,大多数C++库只提供主机侧代码;并不是为了在GPU上使用而编写的。因此,我对在没有仔细检查的情况下使用非平凡类持谨慎态度

我认为,如果类包含指向动态分配内存的成员,那么将类指针传递给内核是很困难的

是的,这可能有问题。但是-如果您使用了
cuda::memory::managed::allocate()
cuda::memory::managed::make_unique()
cudamalocmanaged()
,则这应该“正常工作”,即在访问时,相关内存页将根据需要被提取到GPU或CPU。见:

如果我想按值传递[对象到内核],它们应该是非常轻量级的

,因为每个线程都必须从常量内存中读取每个参数,然后才能使用该参数。虽然恒定的内存允许这种情况相对较快地发生,但仍然需要将大量开销降至最低


还要记住,不能通过(C++)引用将任何内容传递给内核;这都是“按值”-对象本身或指向它的指针。

这是一个部分答案,因为如果没有,很难/不可能猜测为什么您会在
arr\u设备中看到无效值。dim1

该结构通过copy传递,因此它的所有内容都复制到每个块的共享内存中

不正确。内核参数存储在恒定内存中,该内存是设备全局的,而不是块特定的。它们不是存储在共享内存中(特定于块)

当线程运行时,它通常将参数从常量内存读入寄存器(同样,不是共享内存)

通常,将结构和类作为参数传递到内核中有多安全

我个人的经验法则是:如果结构/类

  • 是微不足道的可复制;及
  • 它的结构/类的所有成员都是为主机和设备端定义的,或者至少在设计时考虑了GPU的使用
然后,传递给内核应该是安全的

将结构和类作为参数传递到内核[-]是否应该不惜一切代价避免这种做法

。但是请记住,大多数C++库只提供主机侧代码;并不是为了在GPU上使用而编写的。因此,我对在没有仔细检查的情况下使用非平凡类持谨慎态度

我认为,如果类包含指向动态分配内存的成员,那么将类指针传递给内核是很困难的

是的,这个