我有一个可以容纳两个浮点数的数组,并且我有一个 __m128 变量。我只想存储 __m128 变量的前两个浮点数。
我现在正在做的是
_mm_storeu_ps((float*)a, m0); //a is the array, m0 is the __m128 variable
这将 m0 的前两个浮点数放入 a,但它也继续将其最后两个浮点数存储到 a 的内存之外。
我有一个可以容纳两个浮点数的数组,并且我有一个 __m128 变量。我只想存储 __m128 变量的前两个浮点数。
我现在正在做的是
_mm_storeu_ps((float*)a, m0); //a is the array, m0 is the __m128 variable
这将 m0 的前两个浮点数放入 a,但它也继续将其最后两个浮点数存储到 a 的内存之外。
你可以使用_mm_storel_pi
内在的。此内在函数生成单个movlps
指令。这是一个例子。到目前为止,函数 sample1-sample4 演示了建议。Sample5 演示了 _mm_storel_pi 方法。
#include <stdio.h>
#include <intrin.h>
//-----------------------------------------
void sample1 (float *a, __m128 m0)
{
_mm_storeu_ps(a, m0); //a is the array, m0 is the __m128 variable
}
//-----------------------------------------
void sample2 (float *a, __m128 m0)
{
float *p = (float *)&m0;
a[0] = p[0];
a[1] = p[1];
}
//-----------------------------------------
void sample3 (float *a, __m128 m0)
{
_mm_store_ss(&a[0], m0);
_mm_store_ss(&a[1], _mm_shuffle_ps(m0, m0, _MM_SHUFFLE(1,1,1,1)));
}
//-----------------------------------------
void sample4 (float *a, __m128 m0)
{
union { __m128 i; float f[4]; } u;
u.i = m0;
a [0] = u.f[0];
a [1] = u.f[1];
}
//-----------------------------------------
void sample5 (float *a, __m128 m0)
{
_mm_storel_pi ((__m64 *)a, m0);
}
//-----------------------------------------
void printa (float *a)
{
printf ("%g %g %g %g\n", a [0], a [1], a [2], a [3]);
}
//-----------------------------------------
int main (void)
{
__m128 m0 = _mm_set_ps (1.0, 2.0, 3.0, 4.0);
float a [4];
memset (a, 0, sizeof a);
sample1 (a, m0);
printa (a);
memset (a, 0, sizeof a);
sample2 (a, m0);
printa (a);
memset (a, 0, sizeof a);
sample3 (a, m0);
printa (a);
memset (a, 0, sizeof a);
sample4 (a, m0);
printa (a);
memset (a, 0, sizeof a);
sample5 (a, m0);
printa (a);
return 0;
}
//-------------------------------------
输出:
4 3 2 1
4 3 0 0
4 3 0 0
4 3 0 0
4 3 0 0
这是函数的 gcc 4.8.1 x64 代码生成:
0000000000401510 <sample1>:
401510: 0f 28 02 movaps xmm0,XMMWORD PTR [rdx]
401513: 0f 11 01 movups XMMWORD PTR [rcx],xmm0
401516: c3 ret
0000000000401520 <sample2>:
401520: 0f 28 02 movaps xmm0,XMMWORD PTR [rdx]
401523: f3 0f 11 01 movss DWORD PTR [rcx],xmm0
401527: 0f c6 c0 55 shufps xmm0,xmm0,0x55
40152b: f3 0f 11 41 04 movss DWORD PTR [rcx+0x4],xmm0
401530: c3 ret
0000000000401540 <sample3>:
401540: 0f 28 02 movaps xmm0,XMMWORD PTR [rdx]
401543: f3 0f 11 01 movss DWORD PTR [rcx],xmm0
401547: 0f c6 c0 55 shufps xmm0,xmm0,0x55
40154b: f3 0f 11 41 04 movss DWORD PTR [rcx+0x4],xmm0
401550: c3 ret
0000000000401560 <sample4>:
401560: 48 8b 02 mov rax,QWORD PTR [rdx]
401563: 89 01 mov DWORD PTR [rcx],eax
401565: 48 c1 e8 20 shr rax,0x20
401569: 89 41 04 mov DWORD PTR [rcx+0x4],eax
40156c: c3 ret
0000000000401570 <sample5>:
401570: 0f 28 02 movaps xmm0,XMMWORD PTR [rdx]
401573: 0f 13 01 movlps QWORD PTR [rcx],xmm0
401576: c3 ret
你有几个选择:
您可以将指向 a 的指针转换__m128
为 afloat*
并相应地对其进行索引:
float *p = (float *)&m0;
a[0] = p[0];
a[1] = p[1];
有些人更喜欢创建一个由 4 个浮点数和 a 组成的数组__m128
,这在性能方面非常相似。
如果您只想使用 SSE 内在函数,您可以使用_mm_store_ss
and _mm_shuffle_ps
:
_mm_store_ss(&a[0], m0);
_mm_store_ss(&a[1], _mm_shuffle_ps(m0, m0, _MM_SHUFFLE(1,1,1,1)));
SSE 中的 shuffle 指令非常有用,请在此处阅读有关它们的更多信息。