【问题标题】:How to handle cudaFree on globally instantiated variables如何在全局实例化变量上处理 cudaFree
【发布时间】:2017-08-31 07:48:23
【问题描述】:

我有一个用于实例化全局变量的类:

class BitUnpackPtrs
{
public:
    ushort* d_dataIn;

    BitUnpackPtrs() : d_dataIn(NULL) {};

    ~BitUnpackPtrs()
    {
        cudaFree(d_dataIn);
    }

    void update(...) { ... }
};

该类被全局实例化为句柄,以减少 cuda 内存的频繁分配。但是,当我的程序终止时,cuda-memcheck 会产生警告:

由于对 cudaFree 的 CUDA API 调用“驱动程序关闭”,程序命中 cudaErrorCudartUnloading(错误 29)。

处理这个问题的正确方法是什么?我可以删除 cudaFree,但如果稍后在非全局级别使用此类,则会导致内存泄漏。我可以在构造函数中使用一个标志来指示应该如何处理内存。

或者,有没有办法检测 cuda 驱动程序是否正在关闭并且在这种情况下不调用 cudaFree?

【问题讨论】:

  • 不要在构造函数或析构函数中实例化期望调用或必须调用 cuda 运行时 API 函数的类的全局对象。 CUDA 运行时初始化/拆卸可以在程序启动和关闭时对此造成严重破坏,具体取决于您在类构造函数和析构函数中所做的事情。无法检测 cuda 驱动程序是否正在关闭(以不会在 cuda-memcheck 中标记的方式)并且在这种情况下不调用 cudaFree

标签: c++ cuda global-variables dynamic-memory-allocation


【解决方案1】:

不要将此对象设为全局对象,而是在您的 main() 函数中实例化它(或在某个地方被 main() 调用并包装您的应用程序的整个执行)。这将确保您的 cudaFree() 调用在 CUDA 拆卸发生之前被调用。

另一种选择是使用std::shared_ptrcustom deleter,它调用cudaFree()。如果你这样做了,那么 cudaFree() 调用将在最后一个“用户”破坏其共享指针的副本之后发生 - 这是在 main() 完成之前和 CUDA 拆除之前。

【讨论】:

  • 我考虑过使用共享指针,但全局对象实际上是库的一部分。最终,我认为真正的解决方案将需要重构代码。目前,我在构造函数中添加了一个参数来指示析构函数的内存处理。我只是让系统处理 cudaFree。
  • @AaronS:很公平;但请记住,其他用户会阅读此问题,对他们而言,第二种选择可能仍然相关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-12
  • 2013-06-12
  • 2012-10-21
  • 2020-04-19
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
相关资源
最近更新 更多