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

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

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

Ответы

Ответ 1

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

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

Ответ 2

Вам нужен пользовательский распределитель. Вы можете легко создать один над 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

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

Ответ 4

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