繁体   English   中英

具有虚拟继承的对象传递给cuda内核函数

[英]object with virtual inheritance passing to cuda kernel function

我能够将普通对象作为副本传递给内核函数。 但是,当我将虚拟继承添加到类层次结构中时,我收到一条错误消息,指出带有用户定义的复制构造函数的类不能用作内核启动的参数。 但是,我没有用户定义的复制构造函数。 所以我想这是因为虚拟继承的内部实现实现了某些不同类型的复制构造函数。 有人可以解释一下虚拟继承是如何实现的,是否有任何解决方法,或者在编写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支持虚拟功能和其他高级C ++功能,nvcc应该可以通过一种简单的方式允许它。

感谢所有的评论。 根据提供的链接@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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM