通过复制将对象传递给 CUDA 内核会调用其析构函数并过早释放内存

Passing an object to CUDA kernel by copy invokes its destructor and releases memory prematurely

本文关键字:析构函数 调用 内存 释放 CUDA 对象 复制 内核      更新时间:2023-10-16

我有一个使用 cudaMallocManaged 分配dataGPUMatrix类:

class GPUMatrix
{
public:
    GPUMatrix() { };
    GPUMatrix(int rows, int cols, unsigned flags = 0) { cudaMallocManaged(data) ... };
    ~GPUMatrix() { cudaFree(data) ... };
public:
    int rows = 0;
    int cols = 0;
    float *data = nullptr;
};

GPU 只能访问data指针。因此,我像这样定义我的 mat mul 内核(它需要对象的副本):

__global__
void MatMulNaiveKernelMat(const GPUMatrix a, const GPUMatrix b, const GPUMatrix c)...

但是,完成后,它会调用~GPUMatrix()并释放内存。处理这个问题的最佳方法是什么?我无法将指向GPUMatrix的指针或引用传递给内核,因为整个对象不是由cudaMallocManaged分配的,只有data元素是。

构函数始终删除data指针。 但是,默认复制构造函数将具有原始对象的data指针的副本,它不得删除该副本。

解决此问题的一种方法是修改类以保存一个标志,该标志指示data指针是否归该类所有并需要删除。 然后定义一个复制构造函数来适当地设置该标志。

如果副本的寿命超过原始对象,则此方法存在潜在问题,并且还应添加移动构造函数。 然后是复制赋值和移动赋值运算符。 有关详细信息,请参阅此答案。