对齐指针

时间:2016-01-29 09:56:48

标签: c++ memory-alignment

我想将指针p对齐,以便p = a (modulo b)。大多数情况下,对于SIMD对齐,a = 0和b = 32或64,但是当我想微调我的算法以获得缓存关联性时,我可能还需要a = 64和b = 128。

  • std::align不接受任何2的权力作为对象。它将在C ++ 17中修复,但现在没用了
  • __mm_malloc/__free不像我想要的那样便携

到目前为止,我最好的解决方案是将指针强制转换为std::uintptr_t并对整数使用模运算来移动指针。不幸的是,它不可移植,因为投射到std::uintptr_t的指针不是“允许的”。但它适用于我迄今为止尝试的所有平台。

这样的代码会破坏什么样的平台?

3 个答案:

答案 0 :(得分:2)

你可能会寻找这样的东西:

inline size_t AlignHi(size_t size, size_t align)
{
    return (size + align - 1) & ~(align - 1);
}

inline void * Allocate(size_t size, size_t align)
{
#if defined(_MSC_VER) 
    return _aligned_malloc(size, align);
#elif defined(__GNUC__)
    align = AlignHi(align, sizeof(void*));
    size = AlignHi(size, align);
    void * ptr;
    int result = ::posix_memalign(&ptr, align, size);
    return result ? NULL : ptr;
#else
    return malloc(size);
#endif
}

inline void Free(void * p)
{
#if defined(_MSC_VER) 
    _aligned_free(p);
#else
    free(p);
#endif
}

答案 1 :(得分:0)

  

std :: align不接受任何2的权力作为对象。我将在C ++ 17中修复,但它现在没用了

让我们看看标准(草案)的内容。

  

<强> [ptr.align]

     

2要求:

     

(2.1) - 对齐应该是在此上下文中由实现支持的基本对齐值或扩展对齐值。

因此,允许任何基本对齐值,如果实现允许,则可能允许其他对齐值。让我们看看基本对齐是什么。

  

<强> [basic.align]

     

2 基本对齐由小于或等于所有上下文中实现所支持的最大对齐的对齐来表示,它等于alignof(std :: max_align_t)... < / p>

确定。然后对所有路线都有限制。

  

4对齐表示为std :: size_t类型的值。有效对齐仅包括由基本类型的alignof表达式返回的值以及可能为空的其他实现定义的值集。 每个对齐值应为非负积分 2的幂

因此,不仅允许2个对齐的功率,而且实际上只允许2个对齐的 次幂。与C ++ 17的不同之处在于,在此之前,只允许小于或等于alignof(std::max_align_t)的对齐(即基本对齐)。支持更大的对齐取决于实现。

TL; DR你的前提是错误的。但是std::align是否有效,仍然是在C ++ 17之前定义的实现。

答案 2 :(得分:0)

以下C ++代码要求alignment是2的幂。分配了malloc_aligned的内存必须与free_aligned一起发布:

void *
malloc_aligned(std::size_t alignment, std::size_t size)
{
    alignment = std::max(alignment, alignof(void *));
    size     += alignment;

    void *ptr  = std::malloc(size);
    void *ptr2 = (void *)(((uintptr_t)ptr + alignment) & ~(alignment-1));
    void **vp  = (void**) ptr2 - 1;
    *vp        = ptr;
    return ptr2;
}

void
free_aligned(void *ptr)
{
    std::free(*((void**)ptr-1));
}