2014-01-30 37 views
0

我能够将普通对象作为副本传递给内核函数。但是,当我将虚拟继承添加到类层次结构时,我收到一条错误消息,指出具有用户定义的副本构造函数的类不能用作内核启动的参数。但是,我没有用户定义的复制构造函数。所以我想这是因为虚拟继承的内部实现实现了一些不同类型的复制构造函数。有人可以解释虚拟继承是如何实际实现的吗?是否有任何解决方法,或者在编写cuda代码时绝对没有办法使用虚拟继承?虚拟继承传递给cuda内核函数的对象

的代码是这样的:

class Base {...}; 
class ChildA: public virtual Base {...}; 
class ChildB: public virtual Base {...}; 
class GrandChild: public ChildA, public ChildB {...}; 

__global__ void mykernel(Base x) {...} 

int main() { 
    GrandChild x; 
    mykernel<<<1,1>>>(x); 
    return 0; 
} 

编辑: 这是我的猜测:我觉得NVCC只允许默认的拷贝构造函数,因为在这种情况下,它可以简单地使用cudaMemcpyAsync的论点推入设备内部的调用堆栈。所以它对编译器进行了硬编码,使得只允许使用默认的复制构造函数,但是具有虚拟继承的对象在内部具有不同类型的复制构造函数,从而触发了nvcc中的错误。不过,我仍然相信nvcc应该有一个简单的方法允许它,只要nvcc支持虚函数和其他高级C++功能。

+0

在这里看看它是如何实现的(在gcc中)http://www.phpcompiler.org/articles/virtualinheritance.html;它可能会给你一个第一个想法。只要虚拟功能得到支持,我就不会看到支持虚拟继承的技术限制的简单解释。 – Joky

+0

您正在按值传递x。 – IdeaHat

+0

您可能感兴趣的[this](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#virtual-functions) –

回答

1

感谢您的所有意见。根据@RobertCrovella提供的链接中的以下两条语句,我所做的是不允许的。

  1. 不允许作为参数传递给一个__global__函数的类的一个对象与虚拟功能。
  2. 不允许将从虚拟基类派生的类的对象作为参数传递给__global__函数。

与链路@Joky提供的,我相信原因是因为NVCC使用一个简单的内存拷贝从主机内存参数推到在设备内存中调用堆栈。这就是为什么不允许使用非默认的复制构造函数的原因,因为只有默认的复制构造函数与这种简单的内存复制行为一致。

我正在使用的解决方案是打破一个继承关系并设置一个类型转换运算符以保留上传的缺失链接,如下所示。这对我很好,因为所有这些类只是指针的包装,并且类型转换足够高效,即使价格有时必须进行明确的类型转换,例如在以下调用mykernel2函数的情况。

class Base {...}; 
class ChildA: public Base {...}; 
class ChildB: public Base {...}; 
class GrandChild: public ChildA { 
public: 
    operator ChildB() {...} 
}; 

__global__ void mykernel(Base x) {...} 
__global__ void mykernel2(ChildB y) {...} 

int main() { 
    GrandChild x; 
    mykernel<<<1,1>>>(x); 
    mykernel2<<<1,1>>>(ChildB(x)); 
    return 0; 
}