c-SSE半载(_mm_loadh_pi / _mm_loadl_pi)发出警告

我从英特尔网站借来了矩阵求逆算法:
http://download.intel.com/design/PentiumIII/sml/24504301.pdf

它使用_mm_loadh_pi和_mm_loadl_pi加载4×4矩阵系数并同时进行部分混洗.我的应用程序的性能改善非常显着,如果我使用_mm_load_ps对矩阵进行经典的加载/随机播放,则速度会稍慢一些.

但是这种加载方法会发出编译警告:“ tmp1在此函数中未初始化使用”

__m128 tmp1;
tmp1 = _mm_loadh_pi(_mm_loadl_pi(tmp1, (__m64*)(src)), (__m64*)(src+ 4));

这在某种意义上是有意义的,因为tmp1是_mm_loadl_pi的输入参数,并且会影响结果.

但是,详细查看代码的作用表明tmp1不需要初始化.初始化会稍微减慢代码的速度(可测量).

您是否有关于如何在无需初始化tmp1的情况下以可移植的方式删除警告的想法?

解决方法:

我尝试了3种编译器:MS Visual Studio 2012,gcc481和Intel icl 13.1.正如您所指出的,它们都发出警告.我发现gcc和MS都会自动为tmp1生成初始化代码,即使它们警告缺少初始化. MS编译器生成了不良的内存访问:movaps xmm0,xmmword ptr [rsp]. Gcc生成更有效的xorps xmm0,xmm0.因此,在gcc的情况下,添加tmp1 = _mm_setzero_ps()可以消除警告,并生成与不使用时完全相同的代码.对于MS,添加tmp1 = _mm_setzero_ps()可使代码更短,并且可能更快.只有Intel编译器足够聪明,可以避免不必要的初始化.这是MS和gcc编译器可能的解决方法:

    __m128 tmp1 = _mm_loadh_pi(_mm_load_ps (src), (__m64*)(src + 4));

代码生成为:

movaps      xmm0,xmmword ptr [rcx]
movhps      xmm0,qword ptr [rcx+10h]

它看起来较短,但应进行基准测试以确保速度更快.

2013年9月12日:用于不同警告抑制想法的测试代码:

#include <xmmintrin.h>
#include <stdint.h>
#include <stdio.h>

//---------------------------------------------------------------------------
// original code from http://download.intel.com/design/PentiumIII/sml/24504301.pdf
__m128 func1 (float *src)
    {
    __m128 tmp1;
    tmp1 = _mm_loadh_pi(_mm_loadl_pi(tmp1, (__m64*)(src)), (__m64*)(src+ 4));
    return tmp1;
    }

//---------------------------------------------------------------------------
// original code plus tmp1 initialization
__m128 func2 (float *src)
    {
    __m128 tmp1 = _mm_loadh_pi(_mm_loadl_pi (_mm_setzero_ps (), (__m64*)(src)), (__m64*)(src + 4));
    return tmp1;
    }

//---------------------------------------------------------------------------
// use redundant load to eliminate warning 
__m128 func3 (float *src)
    {
    __m128 tmp1 = _mm_loadh_pi(_mm_load_ps (src), (__m64*)(src + 4));
    return tmp1;
    }

//---------------------------------------------------------------------------

static void dump (void *data)
    {
    float *f16 = data;
    int index;

    for (index = 0; index < 4; index++)
        printf ("%g ", f16 [index]);
    printf ("\n");
    }

//---------------------------------------------------------------------------

int main (void)
    {
    float f [8] = {1, 2, 3, 4, 5, 6, 7, 8};
    __m128 tmp;

    tmp = func1 (f);
    dump (&tmp);
    tmp = func2 (f);
    dump (&tmp);
    tmp = func3 (f);
    dump (&tmp);
    return 0;
    }

构建命令:

gcc  -O3 -Wall -Wfatal-errors sample.c -osample.exe
objdump -Mintel --disassemble sample.exe > disasm.txt

cl -Ox -Zi -W4 sample.c
dumpbin -disasm -symbols sample.exe > disasm.txt

icl -Ox -Zi sample.c                                           
dumpbin -disasm -symbols sample.exe > disasm.txt                  
上一篇:java – 如何摆脱“类路径包含多个SLF4J绑定”的警告?


下一篇:c – 为什么Visual Studio在自我赋值时不会发出警告(int foo = foo;)