_mm256_extractf128_ps(v, 1)
- лучший способ . Если ваш компилятор не компилирует это эффективно, используйте лучший компилятор (например, clang имеет очень хороший оптимизатор перемешивания).
Для младшей половины все компиляторы оптимизируют _mm256_extractf128_ps(v, 0)
, чтобы фактически не использовать vextractf128
инструкция, но самый явный способ сказать, что вы просто хотите низко 128, это _mm256_castps256_ps128
и аналогичные приведенные значения для __m256i
(_mm256_castsi256_si128
) или __m256d
.
Обычно они компилируются только с использованием младшей половины XMM любого регистра YMM, в котором компилятор содержал векторную переменную, хотя некоторые компиляторы пропустили ошибки оптимизации и иногда выдают бесполезную инструкцию vmovaps xmm, xmm
вместо того, чтобы более поздние инструкции читали либо младший xmm, либо полный ymm любого регистра.
Использование математического указателя побуждает компилятор сохранять и перезагружать, что вам обычно не нужно. Но на практике большинство компиляторов большую часть времени оптимизируют его обратно до случайных операций ALU, даже если вы пытались избежать узкого места в случайном порядке и фактически сохраняете / перезагружаете.
I не рекомендуем использовать указатель . Тем не менее, *((__m128*)&variable)
и ((__m128*)&variable)[1]
являются допустимыми, потому что встроенные c векторные типы, такие как __m128
, похожи на char
- им разрешено псевдоним любого другого типа, не нарушая строгое псевдоним и не вызывая неопределенное поведение.
C указатель математика перемещает указатель на 1 единицу размера указанного типа. например, +1
на __m128*
перемещается на 16 байтов, что составляет один __m128
. Вот почему ++
всегда работает, чтобы перебрать указатель на массив. Arinter Arithmeti c
Так как вы хотите 2-й __m128
, вы должны добавить 1
к вашему __m128*
. например, *(1 + (__m128*)&variable)
. C []
синтаксис определен в терминах добавления указателя + разыменования, поэтому мы можем записать его таким образом, применяя []
к результату приведения. Оба этих порядка написания дают понять, что +1
применяется к __m128*
после каста, а не к __m256
с &var
до каста. Хотя IIR C, приведение имеет более высокий приоритет, чем +1
к *((__m128)&var + 1)
, также будет безопасным. Но если вы пишете по-другому, вам не нужно помнить об этом при чтении кода позже.
В GNU C типы intrinsi c определены с __attribute__((may_alias))
. В MSV C алиасинг всегда разрешен. Является ли `reinterpret_cast`ing между указателем вектора аппаратного SIMD и соответствующим типом неопределенным поведением? Это то, что делает приведение указателя безопасным для этого типа наказания.
Любой прочее * Тип 1061 *, такой как ((float*)&vec)[0]
, будет нарушать строгое псевдонимы и будет UB.
Как я уже сказал, поскольку вы обычно хотите, чтобы компилятор использовал инструкции случайного порядка, для работы с указателями требуется, чтобы компилятор оптимизировал все указатели. , Используйте встроенные функции.