【发布时间】:2021-07-26 01:00:05
【问题描述】:
我一直在尝试运行其他一些代码,但在动态共享内存方面遇到了一些问题。根据文档 (https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared),我应该分配一个内存数组,然后将指针类型转换到该数组中的特定位置,如下所示:
extern __shared__ float array[];
short* array0 = (short*)array;
float* array1 = (float*)&array0[128];
int* array2 = (int*)&array1[64];
但是,在我自己的代码中,这并不一定总是有效,我也不太明白为什么。
我的基本结构有 2 个类 A 和 B 以及一个错误检查宏
#define cudaCheckError() { \
cudaError_t err = cudaGetLastError(); \
if(err != cudaSuccess) { \
printf("Cuda error: %s:%d: Error code %d, %s\n", __FILE__, __LINE__, err,cudaGetErrorString(err)); \
exit(1); \
} \
}
class A {
public:
__device__ virtual int foo() const = 0;
};
class B : public A {
public:
__device__ B() {}
__device__ virtual int foo() const override {
return 1;
}
};
和我的内核
__global__
void kernel() {
int idx = threadIdx.x + blockIdx.x * blockDim.x;
extern __shared__ int shared[];
B* b_array = (B *) &shared[0];
if (idx == 0) {
b_array[0] = B();
printf("%i", b_array[0].foo());
}
__syncthreads();
return;
}
调用具有足够共享内存并指定kernel<<<1, 1, 1000>>> 的内核并检查错误代码会产生错误Error code 700, an illegal memory access was encountered。对此运行 cuda-memcheck 也会给出一个错误代码,虽然是一个不同的代码:Error code 719, unspecified launch failure
将内核更改为:
__global__
void kernel() {
int idx = threadIdx.x + blockIdx.x * blockDim.x;
extern __shared__ B shared[];
if (idx == 0) {
shared[0] = B();
printf("%i", shared[0].foo());
}
__syncthreads();
return;
}
并且重新运行会给出预期的输出而不会出现错误。
这是 CUDA 中的派生类和类型转换的某种问题吗?我不是在主机和设备之间复制对象,所以这应该不是问题。是不是不可能像我想要的那样强制转换为对象数组?
【问题讨论】:
-
我在 GPU 上使用虚拟调用和多态性,我认为共享内存可能是您的问题中最少的...... GPU 不是为这种用途而设计的:这应该是非常低效的。话虽如此,您需要初始化对象。你可以尝试做一个新的展示位置来做到这一点。请注意,您不能将指向包含 int 类型项的数组的指针转换为指向对象的指针,因为它会破坏严格的别名规则:这在 C++ 中是非法的(并导致未定义的行为)。
-
基于 CUDA 共享内存文档here,至少在这种情况下,他们似乎并不关心严格的别名。至于继承,我还能如何编写这样的继承层次结构?我的基类确实定义了我可以从对象中获得的一种行为,因此本着 DRY 的精神,我希望能够定义一个对象,并将其作为我的基类的子类传递给函数,而不是为所有类创建单独的函数。
标签: cuda