繁体   English   中英

获得对齐内存的最佳跨平台方法

[英]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 :从标准指定的选项开始,然后回到平台特定的选项。 例如

  1. 如果__STDC_VERSION__ >= 201112L使用aligned_alloc
  2. 如果_POSIX_VERSION >= 200112L使用posix_memalign
  3. 如果定义了_MSC_VER ,请使用Windows内容。
  4. ...
  5. 如果所有其他方法都失败了,只需使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM