C ++ STL выравнивание структуры данных, алгоритм векторизации - PullRequest
12 голосов
/ 09 января 2010

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

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

Ответы [ 5 ]

12 голосов
/ 09 января 2010

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

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

7 голосов
/ 09 января 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 движке).

3 голосов
/ 11 января 2010

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

2 голосов
/ 09 января 2010

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

0 голосов
/ 25 августа 2017

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

...