Thanks for all the comments. According to the following two statements in the link @RobertCrovella provided, what I did is not allowed.
- It is not allowed to pass as an argument to a
__global__
function an object of a class with virtual functions.- It is not allowed to pass as an argument to a
__global__
function an object of a class derived from virtual base classes.
Together with the link @Joky provided, I believe the reason is because nvcc uses a simple memory copy to push arguments from host memory into the call stack in the device memory. This is why no non-default copy-constructor is allowed, because only default copy-constructor is consistent with this simple memory copy behavior.
The solution I'm using is to break one inheritance relationship and setup a type conversion operator to preserve the missing link for upcasting, like the following. This works good for me because all these classes are just wrappers of pointers and type conversion is efficient enough, even though the price is that sometimes I have to do explicit type-conversion, like the case of calling mykernel2
function in the following.
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;
}