_mm_cvtsd_f64 аналог для чисел с плавающей запятой высшего порядка

Я играю с SIMD и задаюсь вопросом, почему нет аналога _mm_cvtsd_f64 для извлечения чисел с плавающей запятой высшего порядка из __m128d.

GCC 4.6+ имеет расширение, которое позволяет добиться этого:

__m128d a = ...;
double d1 = a[0];
double d2 = a[1];

Но в более старом GCC (например, 4.4.) Единственный способ получить это - это определить мою собственную функцию-аналог, используя __builtin_ia32_vec_ext_v2df, то есть:

extern __inline double __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_cvtsd_f64_h (__m128d __A)
{
  return __builtin_ia32_vec_ext_v2df (__A, 1);
}

__m128d a = ...;
double d1 = _mm_cvtsd_f64(a);
double d2 = _mm_cvtsd_f64_h(a);

Это действительно путь? Есть ли альтернатива, которая не использует потенциально специфичный для компилятора материал __builtin? И снова - почему нет предопределенного _mm_cvtsd_f64_h или аналогичного?

Эта альтернатива, которую я мог бы придумать, намного медленнее, кстати:

_mm_cvtsd_f64_h(__m128d __A) {
    double d[2];
    _mm_store_pd(d, __A);
    return d[1];
}

person milianw    schedule 14.10.2013    source источник
comment
MOVHPD, _mm_storeh_pd () должен работать.   -  person Hans Passant    schedule 14.10.2013
comment
Я протестировал предложение Ханса с компиляторами MS и gcc, и я считаю, что он генерирует самый простой код.   -  person    schedule 14.10.2013
comment
Я также только что протестировал это в своем коде, но _mm_storeh_pd кажется на несколько процентов медленнее, то есть между принятым ответом ниже, но быстрее, чем мой плохой подход _mm_cvtsd_f64_h выше.   -  person milianw    schedule 19.10.2013


Ответы (2)


Я предлагаю вам использовать следующий код:

inline static _mm_cvtsd_f64_h(__m128d x) {
    return _mm_cvtsd_f64(_mm_unpackhi_pd(x, x));
}

Это, вероятно, самый быстрый способ получить верхнюю половину регистра xmm, и он совместим с MSVC / icc / gcc / clang.

person Marat Dukhan    schedule 14.10.2013
comment
Спасибо - работает как шарм и работает так же быстро, как встроенная версия, которую я опубликовал выше! - person milianw; 14.10.2013

Вы можете просто использовать объединение:

union {
    __m128d v;
    double a[2];
} U;

Назначьте свой __m128d на U.v и прочтите U.a [0] или U.a [1]. Любой достойный компилятор оптимизирует избыточные хранилища и нагрузки.

person Paul R    schedule 14.10.2013
comment
Ясный регистр УБ - person Severin Pappadeux; 02.01.2018
comment
@SeverinPappadeux: теоретически да, но на практике это настолько распространенное использование, что компиляторы склонны генерировать для него правильный код (или полностью оптимизировать его, где это возможно). - person Paul R; 02.01.2018
comment
@SeverinPappadeux: см. Также этот ответ и, в частности, комментарий @ mafso под ним. - person Paul R; 02.01.2018