Как преобразовать регистр XMM чисел с плавающей запятой одинарной точности в целые числа?

У меня есть куча упакованных чисел с плавающей запятой внутри регистра XMM (с использованием встроенных функций SSE):

__m128 xmm = _mm_set_ps(4.0f, 3.0f, 2.0f, 1.0f);

Я хотел бы преобразовать все это в целые числа за один раз. Я нашел встроенный, который делает то, что я хочу (_mm_cvtps_pi16()), но дает 4x16-битное short вместо полноразмерного int. Внутренняя функция с именем _mm_cvtps_pi32() возвращает int, но только для двух нижних значений в xmm. Я могу использовать его, извлекать значения, перемещать вещи и использовать снова, но есть ли способ попроще? Почему не было бы простой 32-битной упакованной инструкции с плавающей запятой -> 32-битное целое число? Неужели оба помещаются в одно и то же пространство регистра XMM?

РЕДАКТИРОВАТЬ: Хорошо, теперь я вижу, что _mm_cvtps_pi32() возвращает __m64 вместо __m128, что означает, что он работает с регистром MM ... в стиле MMX. Это объясняет, почему он возвращает только два int, но теперь мне интересно:

  • Возникнут ли у меня проблемы при компиляции для x64? Сообщается, что __m64 там не поддерживается ...
  • Почему они не расширили эту инструкцию после выхода SSE?

Спасибо!


person neuviemeporte    schedule 17.09.2013    source источник


Ответы (2)


Согласно эта документация: __m128d _mm_cvtps_epi32(__m128d a) генерирует cvtps2dq инструкцию, которая делает то, что вы хотите.

person Mats Petersson    schedule 17.09.2013
comment
Стоит уделить время пониманию суффиксов. В этом случае pi32 вопроса ведет непосредственно к epi32 этого ответа - e для расширенного. Расширенное, параллельное, целое 32 бита. - person Ben Jackson; 18.09.2013
comment
Раньше я думал, что __m128d используется для хранения двух 64-битных чисел с плавающей запятой, поэтому я не смотрел на эту встроенную функцию более внимательно. Есть идеи, почему этот тип возвращаемого значения? - person neuviemeporte; 18.09.2013
comment
Ладно, похоже, что мы оба ошибались, тип возвращаемого значения на самом деле __m128i, и сейчас все в порядке. Внутренняя функция описана в разделе __m128d документации SSE2 на MSDN, однако по непонятной мне причине. - person neuviemeporte; 18.09.2013
comment
Я не могу поручиться за документацию (я ее не писал, я просто искал нужную инструкцию), но похоже, что другой ответ также предлагает _mm_cvtps_epi32, поэтому, возможно, стоит попробовать эту. - person Mats Petersson; 18.09.2013
comment
Большое тебе спасибо. Просто эти документы меня очень сбивают с толку. Принимаю сейчас. - person neuviemeporte; 18.09.2013
comment
Да, сначала ищу инструкцию в своих книгах, потом ищу в гугле ... - person Mats Petersson; 18.09.2013
comment
Похоже, на странице, на которую вы ссылаетесь, есть ошибки - внутреннее значение должно быть: __m128i _mm_cvtps_epi32 (__m128 a) - Я рекомендую использовать Intel Intrinsics Guide для поиска этого материала, а не в Google или Microsoft. - person Paul R; 18.09.2013

Используйте документацию (_mm_cvtps_epi32):

Документация по Magic.

person Jakub Świerk    schedule 17.09.2013
comment
Я думаю, это плохо для меня из-за того, что я придерживаюсь документов MSDN. Я решил, что это правильный путь, поскольку я пишу на Visual C ++ для Windows. - person neuviemeporte; 18.09.2013
comment
Иногда вам нужно искать глубже: документация MSDN < / а> - person Jakub Świerk; 18.09.2013
comment
Более полезный справочник - Intel Intrinsics Guide - это инструмент документации для Linux / Windows / OS X, и он намного более полный / точный и более быстрый / простой в использовании, чем MSDN. - person Paul R; 18.09.2013