3

我在玩 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];
}
4

2 回答 2

3

我建议您使用以下代码:

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

这可能是获取xmm寄存器上半部分的最快方法,并且与 MSVC/icc/gcc/clang 兼容。

于 2013-10-14T12:27:12.177 回答
0

你可以只使用一个联合:

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

将您的 __m128d 分配给 Uv 并回读 Ua[0] 或 Ua[1]。任何体面的编译器都会优化掉多余的存储和加载。

于 2013-10-14T11:43:57.783 回答