Следующий вопрос связан, однако ответы на старые, и комментарий от пользователя Marc Glisse предполагает , что есть новые подходы , начиная с C ++ 17 к решению этой проблемы , которые не могут быть адекватно обсуждены.
Я пытаюсь выровнять память, работающую правильно для SIMD, при этом все еще имея доступ ко всем данным.
В Intel, если я создаю вектор типа float __m256
и уменьшаю свой размер в 8 раз, это дает мне выровненную память.
Например std::vector<__m256> mvec_a((N*M)/8);
Немного хакерским способом я могу приводить указатели на векторные элементы для плавания, что позволяет мне получать доступ к отдельным значениям плавания.
Вместо этого я бы предпочел иметь std::vector<float>
правильно выровненный, и, следовательно, может быть загружен в __m256
и другие типы SIMD без segfaulting.
Я искал в align_alloc .
Это может дать мне массив в стиле C, который выровнен правильно:
auto align_sz = static_cast<std::size_t> (32);
float* marr_a = (float*)aligned_alloc(align_sz, N*M*sizeof(float));
Однако я не уверен, как это сделать std::vector<float>
. Предоставление std::vector<float>
владения marr_a
не представляется возможным .
Я видел несколько предложений о том, что мне следует написать собственный распределитель , но это похоже на большую работу, и, возможно, с современным C ++ есть лучший способ?
_mm256_loadu_ps(&vec[i])
. (Несмотря на то, обратите внимание , что с параметрами настройки по умолчанию, GCC расщепляется не гарантируемой выровнен 256-битовые нагрузок / магазинов в vmovups XMM / vinsertf128. Так что это преимущество для использования_mm256_load
более ,loadu
если вы заботитесь о том , как ваш код компилируется на GCC если кто - то забывает использовать-mtune=...
или-march=
варианты.)Ответы:
Все контейнеры в стандартной библиотеке C ++, включая векторы, имеют необязательный параметр шаблона, который задает распределитель контейнера , и на самом деле его реализация не так уж и сложна:
Вам придется написать немного кода, который реализует ваш распределитель, но он не будет намного больше кода, чем вы уже написали. Если не требуется предварительно C ++ 17 поддержки вам нужно только реализовать выделить () и DEALLOCATE () методы, это все .
источник
allocator_traits
vector<float, MAA>
несовместимо с типомvector<float>
(и не может быть, потому что все, что делает.push_back
на простойstd::vector<float>
скомпилированной без этого распределителя, может сделать новое распределение и скопировать в минимально выровненную память. И new / delete не совместим с align_alloc / free)std::vector
массива. Например, я мог бы представить реализациюstd::vector
использования только одного указателя на выделенную память, которая хранит конец / емкость / распределитель в памяти до диапазона значений. Это может легко помешать выравниванию, выполненному распределителем.std::vector
это гарантирует. Вот для чего он это использует. Возможно, вам следует рассмотреть то, что стандарт C ++ определяет здесь.allocator_traits
- нет, они этого не делают. Все, что нужно, это реализовать совместимый распределитель.