@safe containers with std.experimental.allocator

bitwise via Digitalmars-d digitalmars-d at puremagic.com
Sat Jan 21 17:05:12 PST 2017


On Saturday, 21 January 2017 at 23:24:52 UTC, Andrei Alexandrescu 
wrote:
> 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.

I don't understand what's questionable about it. I don't see how 
abstracting the alignment away from the consumer of an allocator 
is a bad thing.

>> Considering the above use case, alignedAllocate() is 
>> redundant, and
>> possibly confusing.
>
> Well, you just made use of it in the rigged allocator.

I made use of what I would expect to be a non-member helper 
function. I'm saying that I don't believe alignedAllocate() 
should be a part of the standard interface of an allocator, and 
that allocators should be specialized such that allocate() 
returns memory with whatever alignment is needed.


>> 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.

But how much time? Visual studio always lags behind in standards 
conformance.

Also, there is still the fact that some may need to use 
home-grown aligned allocation functions like the ones I linked 
above that prepend metadata to the memory returned, in which case 
they will need specialized deallocation functions.


More information about the Digitalmars-d mailing list