SSE лучший способ установить регистр на 0.0 и 1.0?

Я занимаюсь математикой sse vector3.

Обычно я устанавливаю 4-ю цифру своего вектора на 1.0f, так как это делает большую часть моей математической работы, но иногда мне нужно установить ее на 0.0f.

Итак, я хочу изменить что-то вроде: (32.4f, 21.2f, -4.0f, 1.0f) на (32.4f, 21.2f, -4.0f, 0.0f)

Мне было интересно, какой лучший способ сделать это:

  1. Преобразование в 4 числа с плавающей запятой, установка 4-го числа с плавающей запятой, отправка обратно в SSE
  2. xor зарегистрируйтесь с самим собой, затем сделайте 2 перетасовки
  3. Выполните всю математику SSE с 1.0f, а затем установите переменные такими, какими они должны быть, когда закончите.
  4. Другой?

Примечание. Вектор уже находится в регистре SSE, когда мне нужно его изменить.


person Pubby    schedule 04.02.2011    source источник
comment
Было бы неплохо, если бы они выпустили версию SSE, которая работала бы с тремя скалярами одновременно!   -  person David Heffernan    schedule 04.02.2011
comment
бит и с 0xfff..ff00000000?   -  person Anycorn    schedule 04.02.2011


Ответы (5)


Предполагая, что ваш исходный вектор находится в xmm0:

; xmm0 = [x y z w]
xorps %xmm1, %xmm1         ; [0 0 0 0]
pcmpeqs %xmm2, %xmm2       ; [1 1 1 1] 
movss %xmm1, %xmm2         ; [0 1 1 1]
pshufd $0x20, %xmm1, %xmm2 ; [1 1 1 0]
andps %xmm2, %xmm0         ; [x y z 0]

должен быть быстрым, так как он не обращается к памяти.

person zr.    schedule 09.02.2011
comment
Вы можете сгенерировать маску быстрее, сдвинув регистр всех единиц, чтобы оставить старшее двойное слово со всеми нулями вместо movss+pshufd. (psrldq %xmm2, 4 или pslldq, чтобы сдвинуться в другую сторону и оставить младшее двойное слово обнуленным.). Или, если вы не можете выделить регистр, вы можете просто сохранить маску [1 1 1 0] для andps в памяти. - person Peter Cordes; 19.06.2015
comment
Кроме того, SSE4.1 blendps с обнуленной регистрацией позволит вам легко помещать нули в старший элемент всего двумя инструкциями (xorps и blendps). Но pshufhw $0xa4 Шута действительно лучший, если вы уверены, что старший элемент действительно равен 1.0f и, следовательно, имеет нулевое слово. - person Peter Cordes; 21.06.2015
comment
не могли бы вы предоставить версию этого, используя встроенные функции компилятора? - person matthias_buehlmann; 21.02.2016

И с постоянной маской.

В сборе...

myMask:
.long 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000

...
andps  myMask, %xmm#

где # = {0, 1, 2, ....}

Надеюсь это поможет.

person Sparky    schedule 05.02.2011

Если вы хотите сделать это без доступа к памяти, вы можете понять, что значение 1 содержит нулевое слово, а значение ноль — это все нули. Итак, вы можете просто скопировать нулевое слово в другое. Если у вас есть 1 в старшем двойном слове, pshufhw xmm0, xmm0, 0xa4 должно помочь:

(gdb) ni
4       pshufhw $0xa4, %xmm0, %xmm0
(gdb) p $xmm0.v4_float
$4 = {32.4000015, 21.2000008, -4, 1}
(gdb) ni
5       ret
(gdb) p $xmm0.v4_float
$5 = {32.4000015, 21.2000008, -4, 0}

Аналогичный трюк для других локаций оставляем читателю в качестве упражнения :)

person Jester    schedule 05.02.2011

pinsrw?

person Bill Lynch    schedule 04.02.2011
comment
По какой-то причине GCC не позволяет мне использовать встроенный __builtin_ia32_pinsrw — есть идеи? - person Pubby; 05.02.2011
comment
Попробуйте: __builtin_ia32_pinsrw128 - person Bill Lynch; 05.02.2011
comment
Если мне не изменяет память, PINSRW — это SSE4 и, следовательно, доступен только для процессоров, которые его поддерживают. - person Sparky; 06.02.2011

Почему бы не умножить ваш векторный элемент на [1 1 1 0]? Я почти уверен, что есть инструкция SSE для поэлементного умножения.

Затем, чтобы вернуться к вектору с 1 в 4-м измерении, просто добавьте [0 0 0 1]. Опять же, для этого тоже есть инструкция SSE.

person Alex W    schedule 05.02.2011
comment
Но как мне быстро получить [1 1 1 0] в регистры sse? - person Pubby; 05.02.2011
comment
побитовое И вместо умножения, побитовое ИЛИ вместо сложения. И да, помимо хранения этих констант в памяти, есть проблема с созданием этого значения. - person Peter Cordes; 21.06.2015