启用 arch:SSE2 使程序变慢

Posted

技术标签:

【中文标题】启用 arch:SSE2 使程序变慢【英文标题】:Enabling arch:SSE2 makes program slower 【发布时间】:2012-03-13 21:49:13 【问题描述】:

在 Visual Studio 2010 上,当我在以下代码上启用增强指令集时,实际上会增加执行时间。

void add(float * input1, float * input2, float * output, int size)

    for(int iter = 0; iter < size; iter++)
    
        output[iter] = input1[iter] * input2[iter];
    


int main()


    const int SIZE = 10000000;
    float *in1 = new float[SIZE];
    float *in2 = new float[SIZE];
    float *out = new float[SIZE];
    for(int iter = 0; iter < SIZE; iter++)
    
        in1[iter] = std::rand();
        in2[iter] = std::rand();
        out[iter] = std::rand();
    
    clock_t start = clock();
    for(int iter = 0; iter < 100; iter++)
    
        add(in1, in2, out, SIZE);
    
    clock_t end = clock();
    double time = difftime(end,start)/(double)CLOCKS_PER_SEC;

    system("PAUSE");
    return 0;

在启用 SSE2 的情况下,time 变量我一直得到大约 2.0 秒,但当它是“未设置”时大约是 1.7 秒。我正在构建 Windows 7 64 位,VS 2010 专业版,发布配置,优化速度。

是否有任何解释为什么启用 SSE 会导致执行时间更长?

【问题讨论】:

您是否查看过生成的程序集,看看它是否使用了任何 SSE 指令? 您是使用调试版本还是发布版本? @RetiredNinja 我不太了解汇编,但我可以确认它仅在启用 SSE 的版本上使用 SSE 所需的寄存器(确切地说是 xmm1 和 xmm0)。 new float[SIZE]; 会提供正确对齐的数据(我的意思是与 SSE 对齐)吗? @R.MartinhoFernandes 没关系。 MSVC 不会自动矢量化。这种情况我以前见过几次。由于 MSVC 不进行矢量化,因此 SSE 并不比 x87 FPU 好。因此,微小的差异可以使任何一个都快一点。 【参考方案1】:

在 SSE 代码中将值移入和移出 SSE 寄存器会产生开销,如果您只进行很少的简单计算(如您的示例所示),这可能会超过 SSE 的性能优势。

另请注意,如果您的数据不是 16 字节对齐的,则此开销会显着增加。

【讨论】:

在这种情况下这无关紧要,因为 MSVC 不进行矢量化。所以它只是使用 SSE 寄存器代替 x87 FPU。没有“四处走动”。同样,对齐只适用于向量 SSE - MSVC 不会自行生成。 我以前使用过 SSE 编译器内部函数并注意到它的加速,所以如果你必须明确地使用 SSE,那么首先使用 arch:SSE 编译器选项有什么意义? @Mystical:好点,我实际上并不知道 MSVC 根本不矢量化。不过文档说,它可能会混合使用 x87 和 SSE2 代码,这可能会导致一些移动(尽管我很难想象编译器会在这样一个简单的示例中搞砸)。唯一确定的方法当然是检查程序集。 @JAKE6459 在 x64 上,您可以获得 8 个额外寄存器的好处。至于 x86,我认为代码稍微简单一些,因为 SSE 比 x87 更灵活(不需要xchg 和类似的垃圾)。但它是否产生任何加速是非常有条件的。【参考方案2】:

IMO,依靠编译器进行这些优化通常不是一个好主意。您的代码应该运行得更快(除非编译器已经为您执行此操作,但似乎并非如此)。我建议

1 确保您的数组是 16 字节对齐的

2 在您的内联添加函数中使用 SSE 内在函数:

#include <xmmintrin.h>
inline void add(const float * input1, const float * input2, float * output, int size)

   // assuming here that 
   // - all 3 arrays are 16-byte aligned
   // - size is a multiple of 4
   for(int iter = 0; iter < size; iter += 4)
     _mm_store_ps( output+iter, _mm_mul_ps( _mm_load_ps(input1+iter),
                                            _mm_load_ps(input2+iter) ) );

如果这不能产生更快的代码,那么加载和存储确实会为单个乘法运算产生过多的开销。

【讨论】:

以上是关于启用 arch:SSE2 使程序变慢的主要内容,如果未能解决你的问题,请参考以下文章

MySQL速度变慢,怎么办

Visual C++ (x64) 中的 SSE2 选项

在启用 Aero 的 Windows 7 上运行 .NET 2.0 应用程序窗体应用程序会导致菜单交互使应用程序崩溃

启用 Instagram 聊天 API

启用 xdebug 远程调试使 apache 服务器非常慢

如何使 Chisel 生成带启用的触发器?