GpuMat的空闲内存

时间:2018-03-13 00:53:19

标签: opencv memory-management cuda out-of-memory gpu

我遇到了CUDA设备内存不足的问题。我已经检测到了原因 - 在我的一些成员函数中,我正在返回一个GpuMat构造在我自己的数据上。这里的问题是 - 如何释放这段记忆?

class Test {
  GpuMat test() {
    float* dev_ptr = nullptr;
    cv::Size size(8192,8192);
    cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
    return GpuMat(size, CV_32FC1, dev_ptr);
  }
}
//main
Test t;
while(true) {
  size_t free_mem, total_mem;
  cudaMemGetInfo(&free_mem, &total_mem);
  std::cout << free_mem << std::endl;
  cv::namedWindow("test", CV_WINDOW_OPENGL | CV_WINDOW_NORMAL);
  cv::imshow("test", t.test());
  cv::waitKet(1);
}

您将看到每次迭代的free_mem减少量(相同数量)。

我尝试过创建自定义分配器和setDefaultAllocator,但它不起作用。

class CustomAllocator : public cv::cuda::GpuMat::Allocator
{
    float* m_ptr;
public:
    CustomAllocator(float* p) : cv::cuda::GpuMat::Allocator(), m_ptr(p) {}
    virtual bool allocate(cv::cuda::GpuMat* mat, int rows, int cols, size_t elemsize) override
    {
        return true;
    }
    virtual void free(cv::cuda::GpuMat* mat) override
    {
        cudaFree(m_ptr);
    }
};
// more or less looked like this...
GpuMat test() {
    float* dev_ptr = nullptr;
    cv::Size size(8192,8192);
    cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
    GpuMat retval(size, CV_32FC1, dev_ptr);
    retval.setDefaultAllocator(new CustomAllocator(dev_ptr));
    return retval;
  }

AllocatorGpuMat都没有那么好的文档,所以任何帮助都会受到高度赞赏。

什么样的工作

GpuMat test() {
  float* dev_ptr = nullptr;
  cv::Size size(8192,8192);
  cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float));
  // do processing...
  // clone data so the GpuMat manages it by itself
  auto retval = GpuMat(size, CV_32FC1, dev_ptr).clone();
  // free manually allocated memory
  cudaFree(dev_ptr);
  return retval;
}

正如我现在写下来的那样,我认为最优的方法是首先分配GpuMat,然后使用//do processing...分配data

1 个答案:

答案 0 :(得分:1)

您正在使用涉及用户提供的分配的GpuMat的特定变体。此外,A (AAA)永远不会超出t循环的范围,因此我不清楚任何隐式方法都可以使用。

由于您使用while提供内存分配,我的建议是您应该使用cudaMalloc释放它。因此,简单地说,使cudaFree成为一个类数据成员而不是一个立即/临时变量,并提供一个dev_ptr成员函数来测试这个指针是否为非NULL,如果是,则运行Test::finish()在上面。当然,如果你想通过构造函数/析构函数来处理,你可能会采用不同的方式,并且可能有很多变种。

这是一种可能的方法,在浏览器中编码,未经测试:

cudaFree()

或者,如果您想避免显式调用class Test { float* dev_ptr; public: Test() {dev_ptr = nullptr;} void finish() { if (dev_ptr != nullptr) cudaFree(dev_ptr);} GpuMat test() { cv::Size size(8192,8192); cudaMalloc((void**)&dev_ptr, size.width*size.height*sizeof(float)); return GpuMat(size, CV_32FC1, dev_ptr); } } //main Test t; while(true) { size_t free_mem, total_mem; cudaMemGetInfo(&free_mem, &total_mem); std::cout << free_mem << std::endl; cv::namedWindow("test", CV_WINDOW_OPENGL | CV_WINDOW_NORMAL); cv::imshow("test", t.test()); cv::waitKey(1); t.finish(); } ,只是想重新分配,您可以这样做:

finish()