ybu*_*ill 22 c optimization 64-bit x86 assembly
在调试时,我经常进入memcpy和memset的手写汇编实现.这些通常使用流指令(如果可用),循环展开,对齐优化等实现...我最近也遇到了由于glibc中的memcpy优化而导致的"错误".
问题是:为什么硬件制造商(英特尔,AMD)不能优化具体情况
rep stos
Run Code Online (Sandbox Code Playgroud)
和
rep movs
Run Code Online (Sandbox Code Playgroud)
被认可,并尽可能快地填写和复制他们自己的架构?
Die*_*Epp 24
成本.
memcpy在C库中优化的成本相当低,可能需要几周的开发人员时间.当处理器功能发生变化以保证重写时,您必须每隔几年左右制作一个新版本.例如,GNU glibc和Apple libSystem都有memcpy专门为SSE3优化的产品.
硬件优化的成本要高得多.它不仅在开发人员成本方面更加昂贵(设计CPU比编写用户空间汇编代码要困难得多),但它会增加处理器的晶体管数量.这可能会产生一些负面影响:
从理论上讲,它可能对性能和单位成本产生总体负面影响.
Maxim:如果软件解决方案足够好,请不要在硬件中使用它.
注意:您引用的错误并不是glibcC规范中的错误.它更复杂.基本上,glibc人员表示其memcpy行为与标准中所宣传的完全一样,其他一些人抱怨说memcpy应该别名memmove.
故事的时间:它让我想起了一个Mac游戏开发者在603处理器而不是601(这是从20世纪90年代)运行游戏时的抱怨.601具有对未对齐的负载和存储的硬件支持,性能损失最小.603简单地产生了一个例外; 通过卸载到内核我想象加载/存储单元可以变得更加简单,可能使处理器更快,更便宜.Mac OS超微内核通过执行所需的加载/存储操作并将控制权返回给进程来处理异常.
但是这个开发人员有一个自定义的blitting例程,可以将像素写入屏幕,从而完成未对齐的加载和存储.601上的游戏性能很好,但是在603上是可恶的.大多数其他开发人员都没有注意到他们是否使用了Apple的blitting功能,因为Apple可能会为新的处理器重新实现它.
故事的寓意是,软件和硬件改进都会带来更好的性能.
总的来说,这种趋势似乎与所提到的硬件优化方向相反.虽然在x86中可以很容易地memcpy在汇编中编写,但是一些较新的架构可以为软件卸载更多的工作.特别值得注意的是VLIW架构:Intel IA64(Itanium),TI TMS320C64x DSP和Transmeta Efficeon就是例子.使用VLIW,汇编编程变得更加复杂:您必须明确选择哪些执行单元可以同时执行哪些命令和哪些命令,这是现代x86将为您做的事情(除非它是Atom).所以写作memcpy突然变得更加困难.
这些架构技巧允许您从微处理器中切割出大量硬件,同时保留超标量设计的性能优势.想象一下,芯片的占地面积更接近Atom但性能更接近Xeon.我怀疑编程这些设备的难度是阻碍更广泛采用的主要因素.
Phi*_*hiS 15
我想在其他答案中添加的一件事是,rep movs在所有现代处理器上实际上并不慢.例如,
通常,REP MOVS指令在选择和设置正确方法时有很大的开销.因此,它对于小数据块不是最佳的.对于大块数据,当满足对齐等的某些条件时,它可能非常有效.这些条件取决于特定的CPU(参见第143页).在Intel Nehalem和Sandy Bridge处理器上,这是移动大块数据的最快方法,即使数据未对齐.
[突出显示是我的.]参考:Agner Fog,用汇编语言优化子程序x86平台的优化指南.页.156(另见第16.10节,第143页)[2011-06-08版].
通用与专业
一个因素是那些指令(rep前缀/字符串指令)是通用的,因此它们将处理任何对齐,任意数量的字节或字,并且它们将具有相对于高速缓存和/或寄存器状态等的某些行为.明确无法改变的副作用.
专用内存副本可能仅适用于某些对齐,大小,并且可能与缓存有不同的行为.
手写程序集(在库中或者一个开发人员可能自己实现)可能会在使用它的特殊情况下超出字符串指令实现.对于特殊情况,编译器通常会有几个memcpy实现,然后开发人员可能会有一个"非常特殊"的情况,他们自己推出.
在硬件级别进行此专业化没有意义.太复杂(=成本).
收益递减规律
另一种思考方式是,当引入新功能(例如SSE)时,设计人员进行架构更改以支持这些功能,例如更宽或更高带宽的存储器接口,管道更改,新执行单元等.设计人员是此时不太可能回到设计的"遗留"部分,试图让它加速到最新的功能.这会产生适得其反的效果.如果您遵循这一理念,您可能会问我们为什么首先需要SIMD,对于那些使用SIMD的情况,设计师难道不能让狭窄的指令像SIMD一样快速工作吗?答案通常是不值得,因为更容易投入新的执行单元或指令.