我有一个数组,有两个浮点数的空间,我有一个__m128变量。我想只存储__m128变量的两个第一个浮点数。
我现在正在做的是
_mm_storeu_ps((float*)a, m0); //a is the array, m0 is the __m128 variable
这会将m0的前两个浮点数放入a中,但它也会继续将最后两个浮点数存储在a的内存之外。
答案 0 :(得分:2)
您可以使用_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
答案 1 :(得分:0)
您有几个选择:
您可以将指向__m128
的指针投射到float*
并对其进行索引:
float *p = (float *)&m0;
a[0] = p[0];
a[1] = p[1];
有些人更喜欢创建一个包含4个浮点数和__m128
的数组的并集,其性能非常相似。
如果您只想使用SSE内在函数,则可以使用_mm_store_ss
和_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中的随机播放说明非常有用,请详细了解here。