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

Пиша SSE код за 2D конволюция, но SSE документацията е много оскъдна. Изчислявам точков продукт с _mm_dp_ps и използвам _mm_extract_ps, за да получа резултата от точковия продукт, но _mm_extract_ps връща шестнадесетичен, който представлява число с плаваща величина, и не мога да разбера как да преобразувам това шестнадесетично число с плаваща величина в обикновено плаващо число. Бих могъл да използвам __builtin_ia32_vec_ext_v4sf, който връща float, но искам да запазя съвместимостта с други компилатори.

_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 трябва да връща плаваща единица, а _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 регистър. Не може да извлече скаларен float в нов регистър. За целта използвайте pshufd. (Или insertps с фалшива зависимост). Компилаторът може да използва extractps за добавяне на float към паметта, но единственият случай на използване на _mm_extract_ps, присъщ в C/C++, е получаването на целочислен битов модел на float в скалар uint32_t. Типът, който го връща обратно към float, просто изисква от компилатора да излъчва бавен код. - 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);
    }
}

GitHub нагоре.

Компилирайте и стартирайте:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

Двойни споменати на: _mm_cvtsd_f64 analogon за по-висок порядък с плаваща запетая

Тествано на Ubuntu 19.04 amd64.

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

extern void _mm_store_ss(float*, __m128);

Вижте „xmmintrin.h.“

person SugarD    schedule 20.02.2013