Fare std :: vector alloca memoria allineata

È ansible creare std::vector delle strutture personalizzate per allocare la memoria allineata per un’ulteriore elaborazione con le istruzioni SIMD? Se è ansible fare con Allocator , qualcuno può avere un simile allocatore che potrebbe condividere?

Modifica: Ho rimosso l’ereditarietà di std::allocator come suggerito da GManNickG e ho reso il parametro di allineamento una cosa del tempo di compilazione.

Di recente ho scritto questo pezzo di codice. Non è testato quanto vorrei, quindi vai avanti e segnala errori. 🙂

 enum class Alignment : size_t { Normal = sizeof(void*), SSE = 16, AVX = 32, }; namespace detail { void* allocate_aligned_memory(size_t align, size_t size); void deallocate_aligned_memory(void* ptr) noexcept; } template  class AlignedAllocator; template  class AlignedAllocator { public: typedef void* pointer; typedef const void* const_pointer; typedef void value_type; template  struct rebind { typedef AlignedAllocator other; }; }; template  class AlignedAllocator { public: typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef std::true_type propagate_on_container_move_assignment; template  struct rebind { typedef AlignedAllocator other; }; public: AlignedAllocator() noexcept {} template  AlignedAllocator(const AlignedAllocator&) noexcept {} size_type max_size() const noexcept { return (size_type(~0) - size_type(Align)) / sizeof(T); } pointer address(reference x) const noexcept { return std::addressof(x); } const_pointer address(const_reference x) const noexcept { return std::addressof(x); } pointer allocate(size_type n, typename AlignedAllocator::const_pointer = 0) { const size_type alignment = static_cast( Align ); void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T)); if (ptr == nullptr) { throw std::bad_alloc(); } return reinterpret_cast(ptr); } void deallocate(pointer p, size_type) noexcept { return detail::deallocate_aligned_memory(p); } template  void construct(U* p, Args&&... args) { ::new(reinterpret_cast(p)) U(std::forward(args)...); } void destroy(pointer p) { p->~T(); } }; template  class AlignedAllocator { public: typedef T value_type; typedef const T* pointer; typedef const T* const_pointer; typedef const T& reference; typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef std::true_type propagate_on_container_move_assignment; template  struct rebind { typedef AlignedAllocator other; }; public: AlignedAllocator() noexcept {} template  AlignedAllocator(const AlignedAllocator&) noexcept {} size_type max_size() const noexcept { return (size_type(~0) - size_type(Align)) / sizeof(T); } const_pointer address(const_reference x) const noexcept { return std::addressof(x); } pointer allocate(size_type n, typename AlignedAllocator::const_pointer = 0) { const size_type alignment = static_cast( Align ); void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T)); if (ptr == nullptr) { throw std::bad_alloc(); } return reinterpret_cast(ptr); } void deallocate(pointer p, size_type) noexcept { return detail::deallocate_aligned_memory(p); } template  void construct(U* p, Args&&... args) { ::new(reinterpret_cast(p)) U(std::forward(args)...); } void destroy(pointer p) { p->~T(); } }; template  inline bool operator== (const AlignedAllocator&, const AlignedAllocator&) noexcept { return TAlign == UAlign; } template  inline bool operator!= (const AlignedAllocator&, const AlignedAllocator&) noexcept { return TAlign != UAlign; } 

L’implementazione per le chiamate di allocazione effettive è solo posix ma è ansible estenderla facilmente.

 void* detail::allocate_aligned_memory(size_t align, size_t size) { assert(align >= sizeof(void*)); assert(nail::is_power_of_two(align)); if (size == 0) { return nullptr; } void* ptr = nullptr; int rc = posix_memalign(&ptr, align, size); if (rc != 0) { return nullptr; } return ptr; } void detail::deallocate_aligned_memory(void *ptr) noexcept { return free(ptr); } 

Ha bisogno di C ++ 11, btw.

Nella prossima versione 1.56, la libreria Boost includerà Boost.Align. Tra gli altri helper per l’allineamento della memoria, fornisce boost::alignment::aligned_allocator , che può essere utilizzato come sostituzione drop-in per std::allocator e consente di specificare un allineamento. Vedere la documentazione su https://boostorg.github.io/align/

Sì, dovrebbe essere ansible. Se metti questa domanda su google, otterrai un sacco di codice di esempio, di seguito alcuni risultati promettenti:

https://bitbucket.org/marten/alignedallocator/wiki/Home

http://code.google.com/p/mastermind-strategy/source/browse/trunk/src/util/aligned_allocator.hpp?r=167

https://gist.github.com/1471329