Выравнивание структуры данных C++ STL, векторизация алгоритма

Есть ли способ обеспечить выравнивание контейнера STL по определенному байту, возможно, с помощью атрибута((aligned))? целевые компиляторы не являются Microsoft Visual C++.

Какие библиотеки, если таковые имеются, предоставляют специализированные шаблоны алгоритмов STL, которые имеют конкретную явную векторизацию, например. ССЕ. Меня интересуют компиляторы g++, Intel и IBM XL.


person Anycorn    schedule 08.01.2010    source источник


Ответы (5)


С контейнерами STL вы можете предоставить свой собственный распределитель через необязательный параметр шаблона. Я бы не рекомендовал писать весь распределитель с нуля, но вы можете написать такой, который будет просто оболочкой вокруг new и delete, но гарантирует, что возвращаемая память соответствует вашим требованиям к выравниванию. (Например, если вам нужно n байта с выравниванием по 16 байтам, вы используете new для выделения n + 15 байтов и возвращаете указатель на первый выровненный по 16 байтам адрес в этом блоке.)

Но может быть достаточно просто добавить атрибут выравнивания к типу элемента. Это выходит за рамки стандарта, поэтому вам придется проверить документацию вашего компилятора и попробовать.

person Adrian McCarthy    schedule 08.01.2010

Вам нужен пользовательский распределитель. Вы можете легко построить его поверх std::allocator:

template <typename T, size_t TALIGN=16, size_t TBLOCK=8>
class aligned_allocator : public std::allocator<T>
{
public:
     aligned_allocator() {}
     aligned_allocator& operator=(const aligned_allocator &rhs){
         std::allocator<T>::operator=(rhs);
         return *this;
     }

     pointer allocate(size_type n, const void *hint){
         pointer p = NULL;
         size_t count = sizeof(T) * n;
         size_t count_left = count % TBLOCK;
         if( count_left != 0 )
         {
             count += TBLOCK - count_left;
         }
         if ( !hint )
         {
             p = reinterpret_cast<pointer>(aligned_malloc(count,TALIGN));
         }else{
             p = reinterpret_cast<pointer>(aligned_realloc((void*)hint,count,TALIGN));
         }
         return p;
     }

     void deallocate(pointer p, size_type n){
         aligned_free(p);
     }

     void construct(pointer p, const T &val){
         new(p) T(val);
     }

     void destroy(pointer p){
         p->~T();
     }
};

Здесь не хватает только aligned_malloc, aligned_realloc и aligned_free. Вам нужно либо реализовать их самостоятельно (это не должно быть так сложно), либо найти их версии в Интернете (я видел по крайней мере одну в движок OGRE).

person Kornel Kisielewicz    schedule 09.01.2010
comment
@ Anycorn, ты когда-нибудь реализовывал это? Кажется, было бы здорово завершить пример Корнела Кисилевича здесь, потому что я не вижу хорошего примера этого где-либо еще в Интернете. - person David Doria; 29.08.2012

Вы уже получили несколько хороших ответов, но, похоже, стоит добавить, что C++ 0x включает std::align(), что должно немного упростить реализацию подобных вещей.

person Jerry Coffin    schedule 10.01.2010
comment
Есть ли где-нибудь пример использования этого в качестве распределителя? - person David Doria; 29.08.2012

Вам нужен собственный распределитель, который возвращает выровненное хранилище. Это должно решить вашу проблему.

person Macke    schedule 08.01.2010

Вместо написания собственного распределителя, как предлагалось ранее, вы можете использовать boost::alignment::aligned_allocator.

person Dev Null    schedule 25.08.2017