[英]best cross-platform method to get aligned memory
这是我通常用于通过Visual Studio和GCC获得对齐内存的代码
inline void* aligned_malloc(size_t size, size_t align) {
void *result;
#ifdef _MSC_VER
result = _aligned_malloc(size, align);
#else
if(posix_memalign(&result, align, size)) result = 0;
#endif
return result;
}
inline void aligned_free(void *ptr) {
#ifdef _MSC_VER
_aligned_free(ptr);
#else
free(ptr);
#endif
}
这个代码一般是好的吗? 我也看到人们使用_mm_malloc
, _mm_free
。 在大多数情况下,我想要对齐内存,使用SSE / AVX。 我可以一般使用这些功能吗? 它会使我的代码更简单。
最后,创建我自己的函数来对齐内存很容易(见下文)。 为什么会有这么多不同的常用函数来获得对齐的内存(其中许多只能在一个平台上运行)?
此代码执行16字节对齐。
float* array = (float*)malloc(SIZE*sizeof(float)+15);
// find the aligned position
// and use this pointer to read or write data into array
float* alignedArray = (float*)(((unsigned long)array + 15) & (~0x0F));
// dellocate memory original "array", NOT alignedArray
free(array);
array = alignedArray = 0;
请参阅: http : //www.songho.ca/misc/alignment/dataalign.html以及如何仅使用标准库分配对齐的内存?
编辑:如果有人关心,我从Eigen(Eigen / src / Core / util / Memory.h)得到了我的aligned_malloc()函数的想法
编辑:我刚刚发现posix_memalign
未定义。 但是, _mm_malloc
适用于Visual Studio 2012,GCC,MinGW和Intel C ++编译器,因此它似乎是最方便的解决方案。 它还需要使用自己的_mm_free
函数,尽管在某些实现中,您可以将指针从_mm_malloc
传递给标准的free
/ delete
。
只要您可以调用特殊功能来执行释放,您的方法就可以了。 我会以相反的方式做你的#ifdef
:从标准指定的选项开始,然后回到平台特定的选项。 例如
__STDC_VERSION__ >= 201112L
使用aligned_alloc
。 _POSIX_VERSION >= 200112L
使用posix_memalign
。 _MSC_VER
,请使用Windows内容。 malloc
/ free
并禁用SSE / AVX代码。 如果你想将分配的指针传递给free
,问题就更难了; 这在所有标准接口上都有效,但在Windows上却没有,并且不一定与某些类似unix的系统具有传统的memalign
功能。
你提出的第一个功能确实可以正常工作。
你的“自制”功能也有效,但缺点是如果值已经对齐,你就浪费了15个字节。 有时可能无关紧要,但OS可能能够提供正确分配而没有任何浪费的内存(如果需要将其对齐到256或4096字节,则可能会因添加“alignment-1”而浪费大量内存)字节)。
这是一个固定的user2093113的示例,直接代码没有为我构建(void * unknown size)。 我还把它放在模板类中,覆盖operator new / delete,这样你就不必进行新的分配和调用。
#include <memory>
template<std::size_t Alignment>
class Aligned
{
public:
void* operator new(std::size_t size)
{
std::size_t space = size + (Alignment - 1);
void *ptr = malloc(space + sizeof(void*));
void *original_ptr = ptr;
char *ptr_bytes = static_cast<char*>(ptr);
ptr_bytes += sizeof(void*);
ptr = static_cast<void*>(ptr_bytes);
ptr = std::align(Alignment, size, ptr, space);
ptr_bytes = static_cast<char*>(ptr);
ptr_bytes -= sizeof(void*);
std::memcpy(ptr_bytes, &original_ptr, sizeof(void*));
return ptr;
}
void operator delete(void* ptr)
{
char *ptr_bytes = static_cast<char*>(ptr);
ptr_bytes -= sizeof(void*);
void *original_ptr;
std::memcpy(&original_ptr, ptr_bytes, sizeof(void*));
std::free(original_ptr);
}
};
像这样使用它:
class Camera : public Aligned<16>
{
};
尚未测试此代码的跨平台性。
如果编译器支持它,C ++ 11会添加一个std::align
函数来进行运行时指针对齐。 您可以像这样实现自己的malloc / free(未经测试):
template<std::size_t Align>
void *aligned_malloc(std::size_t size)
{
std::size_t space = size + (Align - 1);
void *ptr = malloc(space + sizeof(void*));
void *original_ptr = ptr;
char *ptr_bytes = static_cast<char*>(ptr);
ptr_bytes += sizeof(void*);
ptr = static_cast<void*>(ptr_bytes);
ptr = std::align(Align, size, ptr, space);
ptr_bytes = static_cast<void*>(ptr);
ptr_bytes -= sizeof(void*);
std::memcpy(ptr_bytes, original_ptr, sizeof(void*));
return ptr;
}
void aligned_free(void* ptr)
{
void *ptr_bytes = static_cast<void*>(ptr);
ptr_bytes -= sizeof(void*);
void *original_ptr;
std::memcpy(&original_ptr, ptr_bytes, sizeof(void*));
std::free(original_ptr);
}
然后你不必保持原始指针值来释放它。 这是100%便携式我不确定,但我希望有人会纠正我,如果不是!
这是我的2美分:
temp = new unsigned char*[num];
AlignedBuffers = new unsigned char*[num];
for (int i = 0; i<num; i++)
{
temp[i] = new unsigned char[bufferSize +15];
AlignedBuffers[i] = reinterpret_cast<unsigned char*>((reinterpret_cast<size_t>
(temp[i% num]) + 15) & ~15);// 16 bit alignment in preperation for SSE
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.