admin管理员组

文章数量:1576349

1.TensorRT内存泄漏问题

最近遇到一个bug,TensorRT4.0.4没有办法进行内存释放,这个官网也有提到,大意就是调用destory函数(内存销毁的函数),一片内存会被释放两次,然后代码就崩溃了.这个参考文献在这里:

(注意:bug产生的条件就是不停调用TensorRT,对其进行初始化,初始化结束后再销毁,反复操作,就能看到相应的内存泄漏)

问题描述:error tensorRT: terminate called after throwing an instance of 'nvinfer1::CudaError' what(): std::exception Aborted (core dumped)]

参考:https://devtalk.nvidia/default/topic/1028517/tensorrt/tensorrt-3-0-1-ssdnormalizeplugin-destroy-fails/1

然后就将TensorRT4.0.4升级到4.1.3后,然后发现destory是可以使用了,但是依然有内存泄漏的问题;现在还在找原因;

 

内存销毁注意事项:

1)delete掉一个void*类型的指针,导致没有调用到对象的析构函数,析构的所有清理工作都没有去执行从而导致内存的泄露; 
代码如下:

class Object {
private:
    void* data;
    const int size;
    const char id;
public:
    Object(int sz, char c):size(sz), id(c){
    data = new char[size];
    cout << "Object() " << id << " size = " << size << endl;
    }
    ~Object(){
    cout << "~Object() " << id << endl;
    delete []data;
    }
};


紧接着使我们的main函数:

int main() {
Object* a = new Object(10, 'A');//Object*指针指向一个Object对象;
void* b = new Object(20, 'B');//void*指针指向一个Object对象;
delete a;//执行delete,编译器自动调用析构函数;
delete b;//执行delete,编译器不会调用析构函数,导致data占用内存没有得到回收;

cout << "Press any key to continue... ..." << endl;
getchar();
return 0;
}


执行结果如下图: 


 
从执行结果看到,并没有执行b指针(void*)所指对象的析构函数,所以delete一个void*的指针可能会造成内存上的泄露!
参考:https://blog.csdn/qq_18824491/article/details/78902636

2)new创建了一组对象数组,内存回收的时候却只调用了delete而非delete []来处理,导致只有对象数组的第一个对象的析构函数得到执行并回收了内存占用,数组的其他对象所占内存得不到回收,导致内存泄露; 
代码如下:

class Object1
{
    int a;
    int b;
};

int main() {
Object1* arry1 = new Object1[100];//创建包含100个Object1的对象数组arry1并返回数组首地址;
Object1* arry2 = new Object1[100];//创建包含100个Object1的对象数组arry2并返回数组首地址;
delete []arry1;//回收了数组arry1里的所有对象动态创建时占用的内存空间;
delete  arry2;//回收了数组arry2里的第一个对象动态创建时占用的内存空间,导致其他99个对象的内存空间泄露;

cout << "Press any key to continue... ..." << endl;
getchar();
return 0;
}

参考:https://blog.csdn/qq_18824491/article/details/78902636

3)unique ptr的内存释放问题,例子代码:

void(*nvPluginDeleter)(INvPlugin*) { [](INvPlugin* ptr) {ptr->destroy(); } };
std::unique_ptr<INvPlugin, decltype(nvPluginDeleter)> m_plugin_ptr{ nullptr, 
nvPluginDeleter };
m_plugin_ptr.release();
m_plugin_ptr =  nullptr;

如果只是使用release只是转让了m_plugin_ptr的内存使用权,但是内存根本就没有释放掉;

正确的做法是这样的:

void(*nvPluginDeleter)(INvPlugin*) { [](INvPlugin* ptr) {ptr->destroy(); } };
std::unique_ptr<INvPlugin, decltype(nvPluginDeleter)> m_plugin_ptr{ nullptr, 
nvPluginDeleter };
m_plugin_ptr.reset();
m_plugin_ptr.release();
m_plugin_ptr =  nullptr;

加入了reset函数,unique ptr的指针就使用void(*nvPluginDeleter)(INvPlugin*) { [](INvPlugin* ptr) {ptr->destroy(); } };释放掉了内存;

4)如果vector中保存的unique ptr的指针指向的内存空间,则一定要进行循环释放,举例如下:

 std::vector<std::unique_ptr<INvPlugin, decltype(nvPluginDeleter)> > m_nvPlugins_plugin;
 if(!m_nvPlugins_plugin.empty()){
        for(int i = 0;i<m_nvPlugins_plugin.size();i++){
            m_nvPlugins_plugin.at(i).reset();
            m_nvPlugins_plugin.at(i).release();
            m_nvPlugins_plugin.at(i) =  nullptr;
        }
        m_nvPlugins_plugin.clear();
    }

4)什么是内存碎片

内存碎片一般是由于空闲的连续空间比要申请的空间小,导致这些小内存块不能被利用。产生内存碎片的方法很简单,举个例:  
    假设有一块一共有100个单位的连续空闲内存空间,范围是0~99。如果你从中申请一块内存,如10个单位,那么申请出来的内存块就为0~9区间。这时候你继续申请一块内存,比如说5个单位大,第二块得到的内存块就应该为10~14区间。  
    如果你把第一块内存块释放,然后再申请一块大于10个单位的内存块,比如说20个单位。因为刚被释放的内存块不能满足新的请求,所以只能从15开始分配出20个单位的内存块。  
    现在整个内存空间的状态是0~9空闲,10~14被占用,15~24被占用,25~99空闲。其中0~9就是一个内存碎片了。如果10~14一直被占用,而以后申请的空间都大于10个单位,那么0~9就永远用不上了,造成内存浪费。  
    如果你每次申请内存的大小,都比前一次释放的内村大小要小,那么就申请就总能成功。

转自:https://wwwblogs/huaiyinxiaojiang/p/7298780.html

2.在tensorRT上同时运行gpu版本的caffe和使用tensorRT加速,处理两项任务;

链接:https://devtalk.nvidia/default/topic/1038745/jetson-tx2/can-i-inference-two-engine-simultaneous-on-jetson-using-tensorrt-/post/5277632/#5277632

但是我自己没有进行验证,若有盆友有深刻理解,可以留言,谢谢

本文标签: TensorRT