Правильно ли использовать alignas(16) для массива[8] m128?

#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 этого нет.