Как преобразовать шестнадцатеричное число с плавающей запятой в число с плавающей запятой в C / C ++ с помощью функции _mm_extract_ps SSE GCC instrinc

Я пишу код SSE для двумерной свертки, но документация по SSE очень скудна. Я вычисляю скалярное произведение с помощью _mm_dp_ps и использую _mm_extract_ps для получения результата скалярного произведения, но _mm_extract_ps возвращает шестнадцатеричное значение, которое представляет собой число с плавающей запятой, и я не могу понять, как преобразовать это шестнадцатеричное число с плавающей запятой в обычное число с плавающей запятой. Я мог бы использовать __builtin_ia32_vec_ext_v4sf, который возвращает число с плавающей запятой, но я хочу сохранить совместимость с другими компиляторами.

_mm_extract_ps (__m128 __X, const int __N)
{
  union { int i; float f; } __tmp;
  __tmp.f = __builtin_ia32_vec_ext_v4sf ((__v4sf)__X, __N);
  return __tmp.i;
}

Какой момент мне не хватает?

Небольшая помощь будет оценена, спасибо.

OpenSUSE 11.2
GCC 4.4.1
C ++
Параметры компилятора
-fopenmp -Wall -O3 -msse4.1 -march = core2
Параметры компоновщика
- lgomp -Wall -O3 -msse4.1 -march = core2


person Tony Alexander Hild    schedule 28.06.2010    source источник


Ответы (4)


Вы должны уметь использовать _MM_EXTRACT_FLOAT.

Между прочим, мне кажется, что _mm_extract_ps и _MM_EXTRACT_FLOAT должны быть наоборот, т.е. _mm_extract_ps должен возвращать float, а _MM_EXTRACT_FLOAT должен возвращать представление int, но что я знаю.

person Paul R    schedule 28.06.2010
comment
Я предполагаю, что это связано с тем, как Intel описывает инструкцию в своей документации, что может быть или не быть ошибкой - заголовки gcc просто реализуют то, что есть в документации. - person Paul R; 28.06.2010
comment
И есть ли какой-нибудь _MM_EXTRACT_DOUBLE? - person Ciro Santilli 新疆再教育营六四事件ۍ 31.05.2019
comment
@CiroSantilli 新疆 改造 中心 996ICU 六四 事件: см. _mm_cvtsd_f64. - person Paul R; 31.05.2019
comment
_mm_extract_ps является неотъемлемой частью SSE4.1 extractps, fp-версии pextrd. dst = память или целочисленный регистр GP, а не регистр XMM. Он не может извлечь скалярное число с плавающей точкой в ​​новый регистр. Для этого используйте pshufd. (Или insertps с ложной зависимостью). Компилятор может использовать extractps для добавления числа с плавающей запятой в память, но единственный вариант использования встроенного _mm_extract_ps в C / C ++ - это преобразование целочисленного битового шаблона float в скаляр uint32_t. Тип, переводящий его обратно в положение с плавающей запятой, просто просит компилятор выдать медленный код. - person Peter Cordes; 01.06.2019

_mm_cvtss_f32(_mm_shuffle_ps(__X, __X, __N)) выполнит свою работу.

person Roman Zavalov    schedule 30.12.2012

И просто чтобы проиллюстрировать все, что было упомянуто до сих пор:

main.c

#include <assert.h>

#include <x86intrin.h>

int main(void) {

    /* 32-bit. */
    {
        __m128 x = _mm_set_ps(1.5f, 2.5f, 3.5f, 4.5f);

        /* _MM_EXTRACT_FLOAT */
        float f;
        _MM_EXTRACT_FLOAT(f, x, 3);
        assert(f == 1.5f);
        _MM_EXTRACT_FLOAT(f, x, 2);
        assert(f == 2.5f);
        _MM_EXTRACT_FLOAT(f, x, 1);
        assert(f == 3.5f);
        _MM_EXTRACT_FLOAT(f, x, 0);
        assert(f == 4.5f);

        /* _mm_cvtss_f32 + _mm_shuffle_ps */
        assert(_mm_cvtss_f32(x) == 4.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 1)) == 3.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 2)) == 2.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 3)) == 1.5f);
    }

    /* 64-bit. */
    {
        __m128d x = _mm_set_pd(1.5, 2.5);
        /* _mm_cvtsd_f64 + _mm_unpackhi_pd */
        assert(_mm_cvtsd_f64(x) == 2.5);
        assert(_mm_cvtsd_f64(_mm_unpackhi_pd(x, x)) == 1.5);
    }
}

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 01.06.2019


extern void _mm_store_ss (float *, __m128);

См. Xmmintrin.h.

person SugarD    schedule 20.02.2013