【发布时间】:2018-08-21 03:31:02
【问题描述】:
我的 CUDA 设备内存不足。我已经检测到原因 - 在我的一些成员函数中,我返回了一个 GpuMat,该 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;
}
Allocator 和 GpuMat 的文档都写得不太好,因此我们将不胜感激。
什么似乎有效
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,然后使用其 data 分配 //do processing...。
【问题讨论】:
-
您正在试验的所有机制都依赖于超出范围的对象并触发类析构函数。如果你不明白这意味着什么,那么你需要修改 C++ 对象模型中的一些非常核心的概念,然后再继续深入
-
好的,你让我明白了,因为我确实认为 test() 返回的 GpuMat 的范围仅限于一次 while 循环迭代。老实说,我仍然不确定为什么不是那样...你能详细说明一下吗?
-
您正在 while 循环中创建类的实例。如果您通过对象构造和销毁来实现正确的分配和解除分配(并且您还没有回答),则对象需要超出范围才能触发销毁。这意味着循环退出后,将为循环内的所有对象释放内存。我不认为这是你想要的行为
-
当然,您可以在循环内定义额外的范围以在每次循环行程后强制销毁
标签: opencv memory-management cuda out-of-memory gpu