15

我在 C++ 中使用基于日志的类来存储非常小的浮点值(否则这些值超出了 的范围double)。当我执行大量乘法时,这具有将乘法转换为总和的额外好处。

但是,在我的算法中的某个时刻,我需要将标准double值除以一个integer值,而不是对*=基于对数的值执行 a。我已经*=为基于日志的类重载了运算符,并且首先通过运行将右侧的值转换为基于日志的值,log()然后将其添加到左侧的值中。因此实际执行的操作是浮点除法log()和浮点求和。

我的问题是首先将分母转换为基于对数的值是否会更快,这将用浮点减法代替浮点除法,产生以下操作链:两次log(),浮点减法,浮点总和。

最后,这归结为浮点除法是比 快还是慢log()。我怀疑一个常见的答案是这取决于编译器和架构,所以我会说我在 darwin 10.3.0 上使用 Apple 的 gcc 4.2。尽管如此,我还是希望得到一个关于这两个运算符的速度的一般评论和/或关于如何自己衡量差异的想法的答案,因为这里可能会有更多事情发生,例如执行执行类型转换的构造函数等等

干杯!

4

4 回答 4

17

你是否多次除以同一个整数?如果是这样,您可以改为乘以1./yourInteger,并且只进行一次除法。如果可能的话,这将比任何一个都快。

至于您的实际问题,它不仅取决于编译器和架构,还取决于微架构和数据。

在您的特定平台(darwin/x86)上,对于当前硬件 i5/i7:除法(1)约 24 个周期,log( )(2)约 35 个周期。然而,由于除法只使用一个指令调度槽,硬件的重排序引擎可以在除法运行时进行其他有用的计算;log( )相比之下,是在软件中实现的,因此处理器将其他计算提升到对数延迟的机会较少。这意味着在实践中,除法通常会更快一些。

1) 来自英特尔优化手册

2)通过调用log( )紧密循环并mach_absolute_time( )用于获取挂壁时间来测量。

于 2010-05-18T19:26:16.420 回答
5

在 x86 架构上,对数比除法花费的时间要长得多:FYL2X为 85 个周期(吞吐量),而FDIV为 40 个周期。如果其他架构有很大不同,我会感到惊讶。使用浮点除法。

于 2010-05-18T17:37:03.517 回答
1

除法的主要问题是,尽管它在大多数现代 CPU 上是一条指令,但它通常具有很高latency的频率(PowerPC 上为 31 个周期 - 不确定 x86 上是什么)。但是,如果您有其他可以与除法同时发出的非相关指令,则可以掩埋其中的一些延迟。因此,答案将在一定程度上取决于您在包含您的除法的循环中拥有什么样的指令组合和依赖项(更不用说您使用的是哪个 CPU)。

话虽如此,我的直觉是,在大多数架构上,divide 会比 log 函数更快。

于 2010-05-18T16:14:01.103 回答
1

我很确定通过任何算法进行对数计算都会比 FP 除法更昂贵。

当然,唯一确定的方法是将其编码并测量代码的性能。从您的描述看来,实现两个版本并并排尝试应该不会太难。

于 2010-05-18T17:20:06.663 回答