对齐指针



我想对齐指针 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。但它适用于我迄今为止尝试过的所有平台。

这样的代码会在什么样的平台上破解?

可能是你在寻找这样的东西:

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
}

以下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));
}

std::align 不接受 2 的任何幂进行对齐。我将在 C++17 中修复,但现在没用

让我们看看标准(草案(是怎么说的。

[对齐]

2 要求:

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

因此,允许

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

[基本对齐]

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

还行。然后对所有对齐方式都有限制。

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

因此,不仅允许 2 个对齐的幂,而且实际上允许 2 个对齐的幂。与 C++17 的区别在于,在此之前,只允许小于或等于 alignof(std::max_align_t) 的对齐(即基本对齐(。对更大一致性的支持取决于实施。

DR:你的前提错了。但std::align是否有效,在C++17之前仍然确定实施。

最新更新