Align pointer

I want to align the pointer p so that p = a (modulo b). In most cases, a = 0 and b = 32 or 64 for SIMD alignment, but I may also need a = 64 and b = 128 when I want to fine-tune my algorithm for cache associativity.

  • std::aligndoes not take the value 2 for alignment. It will be fixed in C ++ 17, but now it is useless.
  • __mm_malloc/__free not as portable as I want

My best solution so far is to point the pointer at std::uintptr_tand use modulo operations for integers to move the pointer. Unfortunately, it is not portable, because dropping a pointer to is std::uintptr_tnot allowed. But it works on all platforms that I have tried so far.

On which platform will such code break?

+4
source share
3 answers

Perhaps you are looking for something like this:

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
}
+2
source

std :: align does not take 2 to align. I will be fixed in C ++ 17, but now it is useless

See what the standard says (draft).

[ptr.align]

2 Requires:

(2.1) - alignment should be a fundamental alignment value or an extended alignment value supported by the implementation in this context.

Thus, any fundamental value of alignment is acceptable, and possibly others, if allowed by the implementation. Let's see what fundamental alignment is.

[basic.align]

2 A , , , alignof (std:: max_align_t)...

Ok. .

4 std:: size_t. , alignof , , , . .

, 2 , 2 . ++ 17 , , alignof(std::max_align_t) (.. ). .

TL; DR . std::align, ++ 17.

0

++ , alignment 2. , wit 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));
}
0

Source: https://habr.com/ru/post/1626496/


All Articles