OpenCV内存池管理(一)

来源:互联网 发布:奇异网络电视 编辑:程序博客网 时间:2024/05/05 15:07

OpenCV提供了一套高效的内存管理方案,提升了内存申请速率,减少了内存碎片,能够很好的提升程序的稳定性,同时支持线程同步。下面是对OpenCV内存管理源码中alloc.cpp的主要函数fastMalloc()fastFree()的解读研究。

1、启用内存池分配内存

OpenCV3.1中(包括之前的版本),默认是不启用内存池分配的。我的办法是对源码修改后重新编译。步骤如下:
  1. 在alloc.cpp中添加头文件#include <Windows.h>;
  2. 将宏CV_USE_SYSTEM_MALLOC改为0;
  3. 将AutoLock在该cpp中的名字替换为其他名字,如TAutoLock。
重新编译后就可以使用了。

2、原理说明

内存池首先分配了一个巨大内存块,大小为1MB,然后在其中划分为一个个的小块,每个小块大小为16KB,每个小块又可按照给定的内存大小分配表划分为29个类型,将每个小块按类型进行大小区段均分。申请内存时首先判断该大小的内存属于哪个类型,然后再在某个小块上进行分配工作。

3、基本结构及参数定义说明

  • 类型表binSizeTab
static const int binSizeTab[MAX_BIN+1] ={ 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 128, 160, 192, 256, 320, 384, 480, 544, 672, 768,896, 1056, 1328, 1600, 2688, 4048, 5408, 8128, 16256 };//29种类型
内存分配查询表MallocTables
struct MallocTables
{
uchar binIdx[MAX_BLOCK_SIZE/8+1];//对要分配的内存大小,能够以O(1)的时间复杂度找到对应的块类型大小
}

  • 最基本的内存块Block

struct Block{    size_t signature;//标记,表明该内存块是该内存池分配的    Block* prev; //上一个Block,不同情况下的意义不同    Block* next; //下一个Block,不同情况下的意义不同    Node* privateFreeList; //当前块的私有自由区段地址链表    Node* publicFreeList; //    uchar* bumpPtr; //当前小块中第一个可用区段地址,该指针只能往endPtr方向偏移累加    uchar* endPtr; //当前小块中最后一个可用区段的尾地址    uchar* data; //块中偏移头部结构后的数据区    ThreadData* threadData; //线程数据指针    int objSize; //当前块类型的大小,对应binSizeTab中的数值    int binIdx; //当前块类型在内存分配查询表MallocTables中的下标    int allocated; //该区块已分配的区段个数    int almostEmptyThreshold; //阈值判断,与是否将该区块作为可用区块的判断有关    CriticalSection cs; //临界区}

  • 巨大内存块BigBlock

struct BigBlock{    BigBlock* next;//下一个巨大内存块    Block* first; //巨大内存块中第一个区块地址    int nblocks; //巨大内存块中区块个数}

  • 内存池基本结构BigBlock

struct BlockPool{    CriticalSection cs;//临界区    Block* freeBlocks; //指向内存池中自由块链表    BigBlock* pool;//指向第一个巨大内存块地址    int bigBlockSize;//巨大内存块的大小    int blocksPerBigBlock;//未使用}

  • 线程数据结构ThreadData

struct ThreadData{Block* bins[MAX_BIN+1][3];//用START、FREE控制每个区段的区块双向链表static DWORD tlsKey;}

4、内存池结构图




1 0
原创粉丝点击