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
