【问题标题】:Passing an object to CUDA kernel by copy invokes its destructor and releases memory prematurely通过复制将对象传递给 CUDA 内核会调用其析构函数并过早释放内存
【发布时间】:2017-10-28 00:08:53
【问题描述】:

我有一个GPUMatrix 类,使用data 分配cudaMallocManaged

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 元素是。

【问题讨论】:

  • 不要在默认构造函数或析构函数中调用CUDA API
  • 我当然可以这样做,但是我必须有一个InitRelease 对方法对吗?并且必须记住给它们打电话,否则会冒着内存泄漏的风险,这似乎很不方便。还是您有其他建议?

标签: c++ class cuda


【解决方案1】:

您的析构函数总是删除data 指针。但是,默认的复制构造函数将拥有原始对象的 data 指针的副本,它不能删除。

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

如果副本比原始对象寿命长,则此方法存在潜在问题,并且还应添加移动构造函数。然后是复制赋值和移动赋值运算符。请参阅this answer 了解更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    相关资源
    最近更新 更多