2

我有一个可以容纳两个浮点数的数组,并且我有一个 __m128 变量。我只想存储 __m128 变量的前两个浮点数。

我现在正在做的是

_mm_storeu_ps((float*)a, m0); //a is the array, m0 is the __m128 variable

这将 m0 的前两个浮点数放入 a,但它也继续将其最后两个浮点数存储到 a 的内存之外。

4

2 回答 2

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    
于 2013-10-14T02:51:03.177 回答
0

你有几个选择:

选项1

您可以将指向 a 的指针转换__m128为 afloat*并相应地对其进行索引:

float *p = (float *)&m0;
a[0] = p[0];
a[1] = p[1];

有些人更喜欢创建一个由 4 个浮点数和 a 组成的数组__m128,这在性能方面非常相似。

选项 2

如果您只想使用 SSE 内在函数,您可以使用_mm_store_ssand _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 指令非常有用,请在此处阅读有关它们的更多信息。

于 2013-10-13T20:20:38.440 回答