Выравнивание структуры данных С++ 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
Вам нужен настраиваемый распределитель, который возвращает выровненную память. Это должно решить вашу проблему.
Ответ 5
Вместо того, чтобы писать свой собственный распределитель, как предлагаемый до, вы можете использовать boost::alignment::aligned_allocator
.