Как загрузить два упакованных 64-битных четырех слова в 128-битный регистр xmm - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть два целых числа UInt64 (т. Е. 64-разрядное четырехзначное слово).

  • они выровнены по 8-байтовой (sizeof(UInt64)) границе (я также могу выровнять их по 16-байт, если это полезно для чего-либо)
  • они упакованы вместе, так что они расположены рядом в памяти

Как мне загрузить их в регистр xmm,например, xmm0:

enter image description here


Я нашел:

movq xmm0, v[0]

, но это только двигает v[0] и устанавливает верхние 64-битные значения в xmm0 в нули:

xmm0 0000000000000000 24FC18D93B2C9D8F

BonusВопросы

  • Как мне их вернуть?
  • Что, если они не соседствуют в памяти?
  • Что если они 4-байт выровнен?

Редактировать

Как указал В. Чанг, endiannessification мало, и я в порядке, если бы он был наоборот:

enter image description here

Моя загадка заключается в том, как их получить и вытащить.

1 Ответ

0 голосов
/ 27 ноября 2018

Для не выровненной 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-битных элементов).

...