以下是我通常用于使用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和 How to allocate aligned memory only using the standard library?
编辑: 如果有人关心,我从Eigen(Eigen / src / Core / util / Memory.h)得到了我的aligned_malloc()函数的想法
编辑:
我刚刚发现MinGW未定义posix_memalign
。但是,_mm_malloc
适用于Visual Studio 2012,GCC,MinGW和Intel C ++编译器,因此它似乎是最方便的解决方案。它还需要使用自己的_mm_free
函数,但在某些实现中,您可以将指针从_mm_malloc
传递到标准free
/ delete
。
答案 0 :(得分:10)
只要您可以通过调用特殊功能来执行释放,您的方法就可以了。我会以相反的方式做你的#ifdef
:从标准指定的选项开始,然后回到平台特定的选项。例如
__STDC_VERSION__ >= 201112L
使用aligned_alloc
。_POSIX_VERSION >= 200112L
使用posix_memalign
。_MSC_VER
,请使用Windows内容。malloc
/ free
并停用SSE / AVX代码。如果您希望能够将分配的指针传递给free
,问题就更难了;这在所有标准接口上都有效,但在Windows上没有,并且不一定与某些类似unix的系统具有遗留memalign
功能。
答案 1 :(得分:4)
你提出的第一个功能确实可以正常工作。
你的“自制”功能也有效,但缺点是如果值已经对齐,你就浪费了15个字节。有时可能无关紧要,但OS可能能够提供正确分配而没有任何浪费的内存(如果需要将其对齐到256或4096字节,则可能会因添加“alignment-1”而浪费大量内存)字节)。
答案 2 :(得分:2)
这是一个固定的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>
{
};
尚未测试此代码的跨平台性。
答案 3 :(得分:1)
如果编译器支持它,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%便携式我不确定,但我希望有人会纠正我,如果没有!
答案 4 :(得分:0)
这是我的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
}