SSE Assembler vs Optimizied C++
打破汇编的神话?
汇编语言对于软件工程人员来说,是高速精简的代称,但同时也是晦涩难懂的代名词。学校的老师,各种各样的书籍宝典,总是举出各种各样的例子来向我们灌输着这样一个定律:C++编译后产生的代码在执行效率上不如汇编编译成机器代码。但是汇编代码在编写的时候晦涩难懂,使得开发效率大为降低。但是在那个CPU寄存器非常珍贵,内存异样稀少的时代,汇编相对C有着独特的优势,可以极其精确的为每一个变量分配寄存器和内存,但是同时也使得开发过程缓慢无比,因为一不留神就会造成寄存器分配冲突。同时由于那个时代的C++的编译器的编译效率不高,造成了编译的时候产生的代码无论在算法和体积上都无法和汇编相比。
最近在编写引擎的时候,一直在汇编的执行效率和C++的编写效率上犹豫不觉。一开始试着编写了2个不同版本的Vector类,叉积分别使用SSE汇编和C++优化。然后我试着编译了这两个不同的版本,编译的时候将所有优化选项全部打开,并最大化速度优先。测试程序对于每个版本调用1亿次叉积运算,总共进行了10次,最后的出的结果令人瞠目结舌。SSE汇编10次测试全部败于C++,C++所用的时间只相当于SSE的三分之一。
今天新编了一个四元数类,同样在从四元数向矩阵的转换中,使用了Intel网站上的Id Software的汇编代码,和C++代码。同样进行速度最大化优化,1亿次转换测试,结果在预测之内,差别虽然没有向量测试的那么惊人,但C++仍然比汇编高效。
新一代编译器都支持在编译时打开SSE增强指令集,这意味着,包括Visual Studio在内的C++编译器,能够在从C/C++到汇编代码的过程中,自动尽可能的使用SSE增强指令集来提高汇编代码效率。手写SSE汇编,由于人员之间的水平差异,不可能将汇编代码优化到最高水准,而编译器使用了高效的算法来优化产生的汇编代码,这使得,一个资质普通的程序员写出的SSE代码,会比由C++编译器编译出的汇编代码要慢的多。当然这个世界上总是有着惊人天赋的天才,一定能够在同等条件下写出比编译器快得多的汇编代码,但是这不具有普遍性,在软件业高速发展的今天,通用性,易用性,费效比,以及重用性才是软件工程中最重要的,而花大钱雇一个汇编高手来写核心意味着这个代码具有最差的移植性,最差的可读性,以及最差的重用性,这是不可取的。
我们应该相信现代编译器能够在最短时间内编译出最优代码,而事实上,这个也已经成为了既定的现实。抛弃手动的SSE汇编,让编译器来完成这项工作,是最明智的做法。当然我们应该在编写C++代码时稍微考虑一下数据流的生成顺序,以便让编译器发挥出最大效能,至于如何优化数据流,将在下一篇中介绍。
ps: 在Visual Studio.NET 2003下,将“启用增强指令集”设置为SSE/SSE2即可。