On 1/21/17 5:44 PM, bitwise wrote:
About alignedMalloc:

In C++ for example, I may want to use a vector full some SIMD type:

class alignas(16) Vec4 {
    union {
        struct { float x, y, z, w; };
        __m128 m;
    };
};

std::vector<Vec4> points = { ... };

In C++ however, 'new' does not respect over-alignment:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0035r2.html

Even if new respected alignment, there is no gauruntee all containers,
STL or otherwise, would use 'new' as opposed to malloc by default(maybe
one day?)

So I use a custom aligned allocator:

template <class T, int ALIGN>
class AlignedAllocator {
    T* allocate(size_type n) {
        return (T*)_aligned_malloc(ALIGN, n * sizeof(T));
    }
};

SIMD operations(aligned load and store) can now safely be used on the
contents of the std::vector<Vec4>.

std::vector knows nothing about the alignment of the memory it uses. It
only knows to call allocate() of whatever allocator it's given. If I had
an allocator with a function 'alignedAllocate' it wouldn't do any good.
I believe this is the _correct_ design, and that a container _shouldn't_
have to know about where from, or what kind of memory it's getting.

I understand. That's a questionable design. It only works by virtue of a long-distance convention between the rigged allocator and the element type of the vector.

Considering the above use case, alignedAllocate() is redundant, and
possibly confusing.

Well, you just made use of it in the rigged allocator.

About missing alignedDeallocate:

while aligned_alloc(), which works in combination with regular 'free()',
is supposed to be standard as of C++11, it's still not supported in
visual studio 2015. Instead, one must use _aligned_malloc, and
_aligned_free. Passing memory from _aligned_malloc to the regular
version of free() causes a crash. Thus, different deallocation methods
are needed for both. Also, there's homegrown aligned_allocate functions
like the following, which require special deallocation functions because
of the exta metadata prepended to the memory:
https://github.com/dlang/phobos/blob/366f6e4e66abe96bca9fd69d03042e08f787d040/std/experimental/allocator/mallocator.d#L134-L134


I suppose you could use aligned allocation for _all_ allocations, even
allocations with default alignment, but that would add extra metadata(at
least 8 bytes) to _all_ allocations even when its unnecessary.

So a solution could be to include the alignment as a template parameter
of Mallocator, or provide an second AlignedMallocator(uint). The
allocate() function of either option would return aligned memory if the
'alignment' template parameter was non-default. Then, the idea of memory
alignment would be abstracted away from the containers themselves.

struct Mallocator(uint alignment = platformAlignment){}){}
or
struct AlignedMallocator(uint alignment = platformAlignment){}){}

It seems a matter of time until aligned_alloc gets implemented on Windows.


Andrei


Reply via email to