规则 1:优化前的配置文件
在投入任何努力相信您可以击败优化器之前,您必须分析所有内容并发现瓶颈的真正所在。一般来说,sqrt() 本身不太可能是您的瓶颈。
规则 2:在替换标准函数之前替换算法
即使sqrt() 是瓶颈,那么仍有合理的可能存在可以消除调用的算法方法(例如按长度平方排序距离,无需调用任何数学函数即可轻松计算) sqrt() 首先。
如果你什么都不做,编译器会为你做什么
许多现代 C 编译器都愿意在更高的优化级别内联 CRT 函数,使自然表达式(包括对 sqrt() 的调用)尽可能快地进行。
特别是,我检查了 MinGW gcc v3.4.5,它将对 sqrt() 的调用替换为对 FPU 状态进行洗牌的内联代码,并在核心使用了 FSQRT 指令。由于 C 标准与 IEEE 754 浮点交互的方式,它确实必须遵循 FSQRT 一些代码来检查异常情况并从运行时库调用真正的 sqrt() 函数,以便浮点异常可由库按标准要求处理。
使用 sqrt() 内联并在更大的 all double 表达式的上下文中使用,在考虑到标准合规性和保持全精度的约束条件下,结果尽可能高效。
对于这种(非常常见的)编译器和目标平台的组合,在不了解用例的情况下,这个结果还不错,代码清晰可维护。
在实践中,任何技巧都会使代码变得不那么清晰,并且可能更难维护。毕竟,您更愿意维护(-b + sqrt(b*b - 4.*a*c)) / (2*a) 还是内联汇编和表格的不透明块?
此外,在实践中,您通常可以依靠编译器和库作者来充分利用您平台的功能,并且通常比您更了解优化的细微之处。
但是,在极少数情况下,可以做得更好。
这样的情况之一是在计算中,您知道自己真正需要多少精度,并且知道您不依赖于 C 标准的浮点异常处理,而是可以与硬件平台提供的东西相处。
编辑:我重新排列了文本,以强调 Jonathan Leffler 在 cmets 中建议的分析和算法。谢谢,乔纳森。
Edit2:修正了 kmm 敏锐的眼睛发现的二次示例中的优先错字。