使用SSE内在函数注册缺少

时间:2013-07-17 10:13:28

标签: c++ memory sse cpu-registers

在这篇文章SSE load/store memory transactions中,我询问了显式寄存器内存事务和中间指针之间的区别。在实践中,中间指针显示略高的性能,但是,不清楚什么是硬件方面的中间指针?如果指针被创建,是否意味着某些寄存器也被占用,或者在某些SSE操作期间发生了寄存器调用(例如_mm_mul)?

让我们考虑一下这个例子:

struct sse_simple
{
    sse_simple(unsigned int InputLength):
        Len(InputLength/4),
        input1((float*)_mm_malloc((float *)_mm_malloc(cast_sz*sizeof(float), 16))),
        input2((float*)_mm_malloc((float *)_mm_malloc(cast_sz*sizeof(float), 16))),
        output((float*)_mm_malloc((float *)_mm_malloc(cast_sz*sizeof(float), 16))),
        inp1_sse(reinterpret_cast<__m128*>(input1)),
        inp1_sse(reinterpret_cast<__m128*>(input2)),
        output_sse(reinterpret_cast<__m128*>(output))
    {}

    ~sse_simple()
    {
        _mm_free(input1);
        _mm_free(input2);
        _mm_free(output);
    }

    void func()
    {
        for(auto i=0; i<Len; ++i)
            output_sse[i] = _mm_mul(inp1_sse[i], inp2_sse[i]);
    }

    float *input1;
    float *input2;
    float *output; 

    __m128 *inp1_sse;
    __m128 *inp2_sse;
    __m128 *output_sse;

    unsigned int Len;
};

在上面的示例中,中间指针inp1_sse,inp2_sse和output_sse在构造函数中创建一次。如果我复制了大量的sse_simple对象(例如50 000或更多),这是否会导致寄存器短缺?

1 个答案:

答案 0 :(得分:2)

首先,寄存器是与计算单元接近(意味着访问速度非常快)的小存储器。编译器尽可能地尝试使用它们来加速计算,但是当它不能使用内存时。由于存储在寄存器中的存储量很小,通常寄存器仅在计算期间用作临时存储器。大多数情况下,一切都最终存储在内存中,除了临时变量,如循环索引......因此,寄存器的不足只会减慢计算速度。

在计算过程中,指针存储在通用寄存器(GPR)中,无论它们指向浮点数,向量还是其他,而向量__m128存储在特定寄存器中。

因此,在您的示例中,树阵列将存储在内存和行

output_sse[i] = _mm_mul(inp1_sse[i], inp2_sse[i]);

编译为:

movaps -0x30(%rbp),%xmm0    # load inp1_sse[i] in register %xmm0
movaps -0x20(%rbp),%xmm1    # load inp2_sse[i] in register %xmm1
mulps  %xmm1,%xmm0          # perform the multiplication the result is stored in %xmm0
movaps %xmm0,(%rdx)         # store the result in memory

正如您所见,指针使用寄存器%rbp%rdx存储。