我可以在CUDA内核中使用实现纯虚函数的类吗?
Can I use a class that implements pure virtual functions inside a CUDA kernel?
我正在努力解决一个似乎有点晦涩的问题。
我正在研究一个框架,在这个框架中,用户可以提供一个抽象基类的实现,经过几个魔术和代码生成的步骤,将在CUDA内核中使用。
我知道
"不允许将带有虚函数的类的对象作为参数传递给全局函数。"
,因为虚表在主机上创建并复制到GPU时将是垃圾。但是我没有将对象传递给内核,而是在内核内部构造对象,这应该不会导致虚函数表问题。
class VirtualBase {
public:
__device__ virtual int getResult() const = 0;
__device__ virtual ~VirtualBase();
};
class Implementation : public VirtualBase {
public:
__device__ Implementation(){};
__device__ int getResult() const { return 42; };
__device__ ~Implementation() {};
};
__global__ void kernel() {
Implementation impl;
int res = impl.getResult();
}
int main(void) {
kernel<<<1, 1>>>();
return 0;
}
代码是用Nsights自动生成的makefile
编译的/Developer/NVIDIA/CUDA-7.5/bin/nvcc -G -g -O0 -std=c++11 -gencode arch=compute_30,code=sm_30 -odir "src" -M -o "src/main.d" "../src/main.cu"
/Developer/NVIDIA/CUDA-7.5/bin/nvcc -G -g -O0 -std=c++11 --compile --relocatable-device-code=false -gencode arch=compute_30,code=compute_30 -gencode arch=compute_30,code=sm_30 -x cu -o "src/main.o" "../src/main.cu"
导致错误
ptxas fatal : Unresolved extern function '_ZN11VirtualBaseD2Ev'
make: *** [src/main.o] Error 255
我在安装了CUDA 7.5的Mac上,但我在安装了Ubuntu 14.10和CUDA 7.0的机器上尝试了同样的事情,产生了相同的结果。
经过几个小时的调试,编写这个问题并盯着ptxas错误,我有一种奇怪的感觉,这是没有找到的基类的析构函数,因为D
接近_ZN11VirtualBaseD2Ev
的末尾。
我寻找了一些方法来修改标识符,实际上,D
代表析构函数(标准构造函数在同一位置有一个C
)。
几个调试语句之后,我意识到,当Implementation impl;
超出作用域时,两个析构函数都被调用,它自己的第一个,然后是基类。由于基类的析构函数没有实现,因此不能调用它,并抛出错误。
编辑:这个析构函数调用当然不是CUDA问题,而是标准的c++例程。此外,正如Robert Crovella在评论中指出的那样,CUDA确实支持实现虚拟函数的类,如果它们在设备上实例化的话。
相关文章:
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 分段 排序函数实现中的错误
- 无法去函数实现 vim
- C++ 20 中的运算符 == 和 <=> 应该作为成员还是自由函数实现?
- 为什么在这种情况下不调用我的虚拟函数实现?
- 我能否通过将函数实现为类对象方法来避免使用互斥锁
- 嵌套的模板结构构造函数实现
- C++接口的工厂函数实现
- 链表中的递归长度函数实现
- 我可以期望某些 STL 函数实现是可自动矢量化的吗?
- 如何将深拷贝构造函数实现到链表中?
- 虚拟 CTOR 的克隆函数实现是否有问题
- 没有捕获列表的 lambda 通常作为普通函数实现吗?
- C++二叉树打印函数实现
- C++:默认构造函数实现
- C++派生类中的纯虚函数实现
- 决定放置函数实现的位置
- 强制实施纯虚函数实现,可能使用不同的参数类型
- 如何让成员函数实现依赖于类的模板参数?
- 我们如何将Ostream函数作为类的成员函数实现,而不是作为朋友函数,以便我可以用作虚拟函数