CPU周期(或者,本质上,“速度”)之间的差异是什么?
x /= y;
和
#include <cmath>
x = sqrt(y);
编辑:我知道操作是不等价的,我只是随意提出x /= y
作为基准x = sqrt(y)
CPU周期(或者,本质上,“速度”)之间的差异是什么?
x /= y;
和
#include <cmath>
x = sqrt(y);
编辑:我知道操作是不等价的,我只是随意提出x /= y
作为基准x = sqrt(y)
您的问题的答案取决于您的目标平台。假设您使用的是最常见的 x86 cpu,我可以给您这个链接http://instlatx64.atw.hu/ 这是测量指令延迟的集合(CPU 需要多长时间才能获得结果)和它们是如何为许多 x86 和 x86_64 处理器流水线化的。如果您的目标不是 x86,您可以尝试自己衡量成本或查阅您的 CPU 文档。
首先,你应该得到一个你的操作的反汇编器(从编译器例如 gcc:gcc file.c -O3 -S -o file.asm
或通过编译二进制的反汇编,例如在调试器的帮助下)。请记住,在您的操作中加载和存储一个值,必须另外计算。
以下是来自 friweb.hu 的两个示例:
对于 SQRT(x87、SSE 和 SSE2 版本)的 Core 2 Duo E6700 延迟 (L)
除法(浮点数):
对于较新的处理器,成本更低,DIV 和 SQRT 几乎相同,例如 Sandy Bridge Intel CPU:
浮点 SQRT 是
浮点除法是
对于 32 位,SQRT 甚至更快。
所以:对于较旧的 CPU,sqrt 本身比 fdiv 慢 30-50 %;对于较新的 CPU,成本是相同的。对于较新的 CPU,这两种操作的成本都比旧 CPU 低;对于更长的浮动格式,您需要更多时间;例如,对于 64 位,您需要 2 倍于 32 位的时间;但是 80 位比 64 位便宜。
此外,较新的 CPU 具有与标量 (x87) 相同速度的向量运算(SSE、SSE2、AVX)。向量是 2-4 个相同类型的数据。如果您可以调整循环以使用相同的操作处理多个 FP 值,您将从 CPU 获得更多性能。
如果平方根函数没有在特殊的硬件或软件中实现,大多数库函数将使用牛顿法计算它,该方法二次收敛。
牛顿法是一种迭代方法:您进行初始猜测,计算试验结果,然后将其用于下一次猜测。你重复,直到你认为你有一个“足够接近”的结果。碰巧你可以用平方根证明你需要多少次迭代。每次通过循环,您都会获得另外两位数的精度,因此大多数实现将在 8-9 个循环内收敛到双精度极限。
如果您仔细阅读本文,您会发现迭代牛顿法每次迭代执行两次减法、一次乘法和一次除法。
作为一般经验法则:浮点除法和平方根都被认为是慢操作(与加法或乘法等快速操作相比)。与除法相比,可以预期平方根的速度大致相同或稍慢(即性能降低约 1 倍 - 2 倍)。例如在Pentium Pro上
除法和平方根的延迟分别为 18 到 36 和 29 到 69 个周期
要获得更准确的答案,您需要深入研究平台的架构手册或执行基准测试。
注意:许多现代平台还提供平方根逆运算,其速度与 sqrt 大致相同,但通常更有用(例如,通过使用 invsqrt,您可以同时计算 sqrt 和 div,每个乘法一次)。