Для не выровненной 128-битной загрузки используйте:
movups xmm0, [v0]
: Перемещение невыровненной плавающей запятой одинарной точности для float
или double
данных.(movupd
на 1 байт длиннее, но никогда не влияет на производительность.) movdqu xmm0, [v0]
: перемещать невыровненное двойное слово
Даже если два четырехсловных слова разделены по границе строки кэша, обычно это лучший выбор для пропускной способности.(На процессорах AMD может быть штраф, если нагрузка не помещается в выровненный 32-байтовый блок строки кэша, а не только в 64-байтовую границу строки кэша. Но в Intel любое смещение в пределах 64-байтовогострока кэша свободна.)
Если ваши нагрузки передают инструкции целочисленной SIMD, вы, вероятно, захотите movdqu
, хотя movups
на 1 байт в машинном коде короче.Некоторые процессоры могут заботиться о «пересечении домена» для разных типов нагрузок.Для магазинов это не имеет значения, многие компиляторы всегда используют movups
даже для целочисленных данных.
См. Также Как можно точно оценить скорость невыровненного доступа на x86_64 для получения дополнительной информации озатраты на не выровненные грузы.(SIMD и другие).
Если они не были смежными, ваш лучший выбор -
movq xmm0, [v0]
: Move Quadword movhps xmm0, [v1]
: Перемещение высокопакетной плавающей запятой одинарной точности .(Нет целочисленного эквивалента, используйте это в любом случае. Никогда не используйте movhpd
, это больше бесполезно, потому что ни один ЦП не заботится о двойных и поплавковых перемешиваниях.)
Или на старых x86, таких как Core2 идругие старые процессоры, в которых movups
работал медленно, даже когда все 16 байтов поступали из одной и той же строки кэша, вы можете использовать
movq xmm0, [v0]
: move quadword movhps xmm0, [v0+8]
: перемещение высокопакетной плавающей запятой одинарной точности
movhps
немного эффективнее, чем SSE4.1 pinsrq xmm0, [v1], 1
(2 моп, невозможно микроплавкий предохранитель в семействе Intel Sandybridge: 1 моп для портов нагрузки, 1 для порта 5).movhps
- это 1 микроплавкий моноблок, но все еще требуются те же внутренние порты: load + shuffle.
См. Руководство по оптимизации x86 от Agner Fog;у него есть глава о SIMD с большим разделом о перемещении данных.https://agner.org/optimize/ И посмотрите другие ссылки в https://stackoverflow.com/tags/x86/info.
Чтобы вернуть данные, movups
может работать как хранилище, так же как и movlps
/ movhps
дляразбросать половинки меча.(Но не используйте movlps
в качестве нагрузки - она сливается, создавая ложную зависимость, против movq
или movsd
.)
movlps
на 1 байт короче movq
, но обаможет хранить младшие 64 бита регистра xmm в памяти.Компиляторы часто игнорируют пересечение доменов (vec-int или vec-fp) для хранилищ, поэтому вы должны и использовать инструкции SSE1 ...ps
, когда они точно эквивалентны.
Во всех случаях AFAIK, без процессоровзаботитесь о float
против double
для чего-либо, кроме фактических инструкций добавления / умножения, нет процессоров с отдельными float
и double
доменами обхода-пересылки.Проект ISA оставляет эту опцию открытой, но на практике не существует наказания за сохранение байта с помощью movups
или movaps
для копирования вокруг вектора double
.Или используя movlps
вместо movlpd
.double
тасования иногда полезны, потому что unpcklpd
похож на punpcklqdq
(чередование 64-битных элементов) против unpcklps
как punpckldq
(чередование 32-битных элементов).