[英]Passing value as a function argument vs calculating it twice?
我记得Agner Fog的优秀指南,64位Linux可以通过寄存器传递6个整数函数参数:
http://www.agner.org/optimize/optimizing_cpp.pdf
(第8页)
我有以下功能:
void x(signed int a, uint b, char c, unit d, uint e, signed short f);
我需要传递一个额外的无符号短参数,总共会产生7个参数。 但是,我实际上可以从现有的6中得到第7个值。
所以我的问题是以下哪项是更好的性能实践:
有问题的操作是一个简单的位移:
unsigned short g = c & 1;
不完全理解x86汇编程序我不太确定寄存器是多么珍贵以及将值重新计算为局部变量是否更好,而不是通过函数调用作为参数传递?
我的信念是,计算两次值会更好,因为它是一个简单的1 CPU循环任务。
编辑我知道我可以对此进行分析 - 但我也想了解两种方法下的情况。 有第7个参数这是否意味着涉及缓存/内存,而不是寄存器?
传递参数的机器约定称为应用程序二进制接口 (或ABI),而x86-64 ABI规范中描述了Linux x86-64。 另请参见x86调用约定 wikipage。
在您的情况下,将c & 1
作为附加参数传递可能是不值得的(因为第 7 个参数在堆栈上传递)。
不要忘记当前的处理器核心(在台式机或笔记本电脑上)经常执行无序执行并且超标量 ,因此c & 1
操作可以与其他操作并行完成,并且可能“没有”成本。
但是将这种微优化留给编译器。 如果您非常关心性能,请使用最新的GCC 4.8编译器和gcc-4.8 -O3 -flto
来编译和链接(即启用链接时优化 )。
顺便说一下,缓存性能比这种微优化更具相关性。 单个高速缓存未命中可能花费与数百个CPU机器指令相同的时间(例如250纳秒)。 传闻目前的CPU大多等待缓存。 您可能希望向__builtin_prefetch
添加一些显式(和明智)调用(请参阅此问题和此答案 )。 但是添加太多这些预取会降低代码速度。
最后,代码的可读性和可维护性应该比原始性能更重要!
巴西尔的答案很好,我只想指出另一件事要记住:
a)堆栈很可能在L1缓存中,因此在堆栈上传递参数不应超过约3个周期。
b)ABI(在这种情况下为x86-64 System V)需要恢复被破坏的寄存器。 一些由呼叫者保存,另一些由被呼叫者保存。 显然,如果再次需要原始内容,则调用者必须保存用于传递参数的寄存器。 但是当您的函数使用的寄存器多于调用者保存的寄存器时,函数需要计算的任何其他临时结果必须进入被调用者保存的寄存器。 因此,该函数最终将堆栈中的寄存器溢出,重新使用寄存器作为临时变量,然后将原始值弹回。
避免访问内存的唯一方法是使用更小,更简单的函数,这需要更少的临时变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.