如何实现设备端CUDA虚拟功能?
我看到CUDA不允许将带有虚拟函数的类传递到内核函数中。有没有解决这个限制的办法 我真的希望能够在内核函数中使用多态性如何实现设备端CUDA虚拟功能?,cuda,virtual-functions,Cuda,Virtual Functions,我看到CUDA不允许将带有虚拟函数的类传递到内核函数中。有没有解决这个限制的办法 我真的希望能够在内核函数中使用多态性 谢谢 罗伯特·克罗维拉评论中最重要的部分是: 这些对象只需在设备上创建即可 所以记住这一点,我正在处理这样的情况:我有一个抽象类函数,然后它的一些实现封装了不同的函数及其求值。这是我的代码的简化版本,我是如何在我的情况下实现多态性的,但我并不是说不能做得更好。。。这将有助于您了解以下内容: class Function { public: __device__ Func
谢谢 罗伯特·克罗维拉评论中最重要的部分是: 这些对象只需在设备上创建即可 所以记住这一点,我正在处理这样的情况:我有一个抽象类函数,然后它的一些实现封装了不同的函数及其求值。这是我的代码的简化版本,我是如何在我的情况下实现多态性的,但我并不是说不能做得更好。。。这将有助于您了解以下内容:
class Function
{
public:
__device__ Function() {}
__device__ virtual ~Function() {}
__device__ virtual void Evaluate(const real* __restrict__ positions, real* fitnesses, const SIZE_TYPE particlesCount) const = 0;
};
class FunctionRsj : public Function
{
private:
SIZE_TYPE m_DimensionsCount;
SIZE_TYPE m_PointsCount;
real* m_Y;
real* m_X;
public:
__device__ FunctionRsj(const SIZE_TYPE dimensionsCount, const SIZE_TYPE pointsCount, real* configFileData)
: m_DimensionsCount(dimensionsCount),
m_PointsCount(pointsCount),
m_Y(configFileData),
m_X(configFileData + pointsCount) {}
__device__ ~FunctionRsj()
{
// m_Y points to the beginning of the config
// file data, use it for destruction as this
// object took ownership of configFilDeata.
delete[] m_Y;
}
__device__ void Evaluate(const real* __restrict__ positions, real* fitnesses, const SIZE_TYPE particlesCount) const
{
// Implement evaluation of FunctionRsj here.
}
};
__global__ void evaluate_fitnesses(
const real* __restrict__ positions,
real* fitnesses,
Function const* const* __restrict__ function,
const SIZE_TYPE particlesCount)
{
// This whole kernel is just a proxy as kernels
// cannot be member functions.
(*function)->Evaluate(positions, fitnesses, particlesCount);
}
__global__ void create_function(
Function** function,
SIZE_TYPE dimensionsCount,
SIZE_TYPE pointsCount,
real* configFileData)
{
// It is necessary to create object representing a function
// directly in global memory of the GPU device for virtual
// functions to work correctly, i.e. virtual function table
// HAS to be on GPU as well.
if (threadIdx.x == 0 && blockIdx.x == 0)
{
(*function) = new FunctionRsj(dimensionsCount, pointsCount, configFileData);
}
}
__global__ void delete_function(Function** function)
{
delete *function;
}
int main()
{
// Lets just assume d_FunctionConfigData, d_Positions,
// d_Fitnesses are arrays allocated on GPU already ...
// Create function.
Function** d_Function;
cudaMalloc(&d_Function, sizeof(Function**));
create_function<<<1, 1>>>(d_Function, 10, 10, d_FunctionConfigData);
// Evaluate using proxy kernel.
evaluate_fitnesses<<<
m_Configuration.GetEvaluationGridSize(),
m_Configuration.GetEvaluationBlockSize(),
m_Configuration.GetEvaluationSharedMemorySize()>>>(
d_Positions,
d_Fitnesses,
d_Function,
m_Configuration.GetParticlesCount());
// Delete function object on GPU.
delete_function<<<1, 1>>>(d_Function);
}
您可以在CUDA内核函数中使用多态性。这些对象只需在设备上创建即可。这通常不会很难做到,即使您需要使用来自主机的数据初始化这些对象。我提供了一个答案,用推力演示了这个概念,但当然它也可以在普通CUDA代码中工作。@Robert Crovella似乎这个问题的根源是虚拟函数表的地址特定于设备。在对象在设备之间移动的多gpu应用程序中,这会产生什么影响?例如,我在设备0上实例化一个多态类,然后将实例memcpy到设备1,其中也有相同类的实例。该对象会破坏memcopied对象,还是会无缝地使用设备1的虚拟函数表?我不希望它工作。虚拟函数表基本上是一组指针。这些指针地址只会精确到要调用它们的设备。事实上,我希望UVA能保证它不会起作用。你也许可以让它在非UVA环境下工作,但我不会指望它。不过,我只是在这里猜测。我自己没试过。这正是我想要的。非常感谢。还有一个问题:在内核或设备函数中调用new或malloc不是一个巨大的性能损失吗?@Acerebral在我的例子中,我没有经历过任何重大的开销,总之,我无法想象更好的方法来解决我的问题,所以即使malloc或new会损害性能,我也不会太在意。我比较了没有抽象类的简单方法,在CPU上创建函数,然后使用cudaMemcpy,但性能几乎相同。我想只有在必要时才能实施解决方案并进行优化。