我遇到了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;
}
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,然后使用//do processing...
分配data
。
答案 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()