我现在正在阅读OPENCV的源代码,这是一个计算机视觉开源库。我对这个功能感到困惑:
#define CV_MALLOC_ALIGN 16
void* fastMalloc( size_t size )
{
uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
if(!udata)
return OutOfMemoryError(size);
uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN);
adata[-1] = udata;
return adata;
}
/*!
Aligns pointer by the certain number of bytes
This small inline function aligns the pointer by the certian number of bytes by
shifting it forward by 0 or a positive offset.
*/
template<typename _Tp> static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp))
{
return (_Tp*)(((size_t)ptr + n-1) & -n);
}
fastMalloc
用于为指针分配内存,该指针调用malloc
函数,然后调用alignPtr
。我无法理解为什么在分配内存后调用alignPtr
?我的基本理解是通过这样做,机器找到指针要快得多。可以在互联网上找到关于这个问题的一些参考吗?对于现代计算机,是否仍然需要执行此操作?任何想法将不胜感激。
答案 0 :(得分:1)
某些平台要求某些类型的数据出现在某些字节边界上(例如: - 某些编译器 要求指针存储在4字节边界上)。
这称为对齐,它要求在对象的数据内,甚至可能在对象的数据末尾进行额外填充。
如果编译器没有找到正确的对齐方式,或者在读取数据时可能存在性能瓶颈(因为需要读取两个块来获取相同的数据),编译器可能会中断。
对评论作出回应: -
程序的内存请求通常由内存分配器处理。一个这样的内存分配器是fixed-size allocator
。固定大小分配返回指定大小的块,即使请求的内存小于该特定大小。所以,在这个背景下,让我试着解释一下这里发生了什么: -
uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
这将分配等于memory_requested + random_size
的内存量。这里random_size
填补了空白,使其适合为固定分配方案指定的大小。
uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN);
这是尝试将指针对齐到特定边界,如上所述。
答案 1 :(得分:1)
它分配的块比你要求的大一点。
然后将adata
设置为下一个正确分配的字节的地址(添加一个字节,然后向上舍入到下一个正确对齐的地址)。
然后它将原始指针存储在新地址之前。我假设这稍后用于释放最初分配的块。
然后我们返回新地址。
只有CV_MALLOC_ALIGN
比malloc
保证更严格的对齐 - 可能是高速缓存行?这才有意义吗?