#c #vectorization #memory-alignment #alignas
Вопрос:
Это код, который я обычно пишу:
alignas(16) __m128 myBuffer[8];
Но может быть (так как массив объектов составляет 128*8 бит = 128 байт) Я должен написать:
alignas(128) __m128 myBuffer[8];
Или «поскольку первые 16 байтов выровнены» в первом примере, остальные будут автоматически выровнены в памяти?
Комментарии:
1. Как вы думаете, зачем
alignas()
это вообще нужно__m128
?2. Имея в виду этот вопрос и ваш вопрос в комментарии, мне интересно, что, по вашему мнению, означает выравнивание, и, возможно, это причина этой путаницы.
3. @гарольд поместил материал в блок, который привязывает значение, указанное функцией? вроде того 🙂
Ответ №1:
128-разрядные типы данных SIMD должны быть выровнены по 16 байтам. Компилятор уже знает об этом, поэтому выравнивание __m128
вручную не требуется. См., например, документы MSVC по __m128
:
Переменные типа
__m128
автоматически выравниваются по 16-байтовым границам.
Кроме того, массивы являются смежными. Каждый элемент массива естественным образом выравнивается так же, как и первый. Нет необходимости умножать выравнивание для массивов.
Так что вам alignas
вообще не нужно беспокоиться:
__m128 myBuffer[8];
Это просто сработает.
Комментарии:
1. так правильно ли его использовать
alignas(4) std::array<float, 4097> mSamples
?2. @markzzz
float
в большинстве случаев уже естественным образом выровнен по 4 байтам, такalignas(4)
что здесь не будет никакой разницы. Если вы хотите выполнять операции SIMD над этим массивом, вам следует использоватьalignas(16)
(или 32 при таргетинге AVX2 или более поздней версии).3. вот в чем вопрос: почему alignas(16) будет отличаться от alignas(4), если они последовательны?
Ответ №2:
правильно ли использовать alignas(16) для массива[8] m128?
Технически это не так, но, согласно документации __m128
, выровнено до 16 байт, поэтому его не нужно использовать alignas
.
Но может быть … Я должен написать:
alignas(128)
Если ваша цель состоит в выравнивании до 128 байт, то вы можете достичь этого таким образом.
Или «поскольку первые 16 байтов выровнены» в первом примере, остальные будут автоматически выровнены в памяти?
Этот вопрос меня смущает. Если целое число выровнено, то выравнивается первый байт. Остальные байты смещены от первого байта. В случае, если размер больше выравнивания, некоторые из последующих байтов будут выровнены со смещениями, равными выравниванию.
Обратите __m128
внимание, что в стандартном C этого нет.