Вы должны использовать пользовательский распределитель с std::
контейнерами, такими как vector
. Не могу вспомнить, кто написал следующий, но я использовал его в течение некоторого времени, и он, кажется, работает (возможно, вам придется изменить _aligned_malloc
на _mm_malloc
, в зависимости от компилятора / платформы):
#ifndef ALIGNMENT_ALLOCATOR_H
#define ALIGNMENT_ALLOCATOR_H
#include <stdlib.h>
#include <malloc.h>
template <typename T, std::size_t N = 16>
class AlignmentAllocator {
public:
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef T & reference;
typedef const T & const_reference;
public:
inline AlignmentAllocator () throw () { }
template <typename T2>
inline AlignmentAllocator (const AlignmentAllocator<T2, N> &) throw () { }
inline ~AlignmentAllocator () throw () { }
inline pointer adress (reference r) {
return &r;
}
inline const_pointer adress (const_reference r) const {
return &r;
}
inline pointer allocate (size_type n) {
return (pointer)_aligned_malloc(n*sizeof(value_type), N);
}
inline void deallocate (pointer p, size_type) {
_aligned_free (p);
}
inline void construct (pointer p, const value_type & wert) {
new (p) value_type (wert);
}
inline void destroy (pointer p) {
p->~value_type ();
}
inline size_type max_size () const throw () {
return size_type (-1) / sizeof (value_type);
}
template <typename T2>
struct rebind {
typedef AlignmentAllocator<T2, N> other;
};
bool operator!=(const AlignmentAllocator<T,N>& other) const {
return !(*this == other);
}
// Returns true if and only if storage allocated from *this
// can be deallocated from other, and vice versa.
// Always returns true for stateless allocators.
bool operator==(const AlignmentAllocator<T,N>& other) const {
return true;
}
};
#endif
Используйте это следующим образом (при необходимости измените 16 на другое выравнивание):
std::vector<T, AlignmentAllocator<T, 16> > bla;
Это, однако, только гарантирует, что используемый блок памяти std::vector
выровнен на 16 байтов. Если sizeof(T)
не кратно 16, некоторые ваши элементы не будут выровнены. В зависимости от вашего типа данных, это может быть не проблема. Если T
равно int
(4 байта), загружаются только элементы, индекс которых кратен 4. Если это double
(8 байтов), только кратны 2 и т. Д.
Реальная проблема в том, что если вы используете классы как T
, в этом случае вам придется указать свои требования выравнивания в самом классе (опять же, в зависимости от компилятора, это может отличаться; пример для GCC):
class __attribute__ ((aligned (16))) Foo {
__attribute__ ((aligned (16))) double u[2];
};
Мы почти закончили! Если вы используете Visual C ++ (по крайней мере, версия 2010), вы не сможете использовать std::vector
с классами, выравнивание которых вы указали, из-за std::vector::resize
.
При компиляции появляется следующая ошибка:
C:\Program Files\Microsoft Visual Studio 10.0\VC\include\vector(870):
error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
Вам придется взломать ваш stl::vector header
файл:
- Найдите заголовочный файл
vector
[C: \ Program Files \ Microsoft Visual Studio 10.0 \ VC \ include \ vector]
- Найдите метод
void resize( _Ty _Val )
[строка 870 в VC2010]
- Измените его на
void resize( const _Ty& _Val )
.