我在C ++中使用基于日志的类来存储非常小的浮点值(因为这些值超出了double
的范围)。由于我正在执行大量乘法运算,因此将乘法转换为总和还有额外的好处。
但是,在我的算法的某个点上,我需要将标准double
值除以integer
值,而不是将*=
除以基于日志的值。我为基于日志的类重载了*=
运算符,并且右侧值首先通过运行log()
转换为基于日志的值,然后添加到左侧值。
因此,实际执行的操作是浮点除法,log()
和浮点求和。
我的问题是,首先将分母转换为基于对数的值会更快,这将使用浮点减法替换浮点除法,从而产生以下操作链:两次log()
,浮点减法,浮点求和。
最后,归结为浮点除法是否比log()
更快或更慢。我怀疑一个常见的答案是这是依赖编译器和体系结构的,所以我会说我在darwin 10.3.0上使用Apple的gcc 4.2。尽管如此,我希望得到一个关于这两个操作员的速度的一般性评论的答案和/或关于如何自己衡量差异的想法,因为这里可能会有更多,例如执行进行类型转换等的构造函数。
干杯!
答案 0 :(得分:12)
你多次除以相同的整数吗?如果是这样,你可以乘以1./yourInteger
,只做一次除法。如果可能的话,那会更快。
至于你的实际问题,它不仅依赖于编译器和体系结构,还依赖于微架构和数据。
在您的特定平台(darwin / x86)上,对于当前硬件i5 / i7:除法(1)约24个周期,log( )
(2)约35个周期。但是,因为除法仅使用单个指令调度槽,所以硬件的重新排序引擎可以在划分飞行时进行其他有用的计算;相反,log( )
在软件中实现,因此处理器将其他计算提升到对数延迟的机会较少。这意味着在实践中,鸿沟通常会更快一些。
1)来自英特尔优化手册
2)通过在紧密循环中调用log( )
并使用mach_absolute_time( )
来获得预留时间来衡量。
答案 1 :(得分:5)
答案 2 :(得分:1)
除法的主要问题是虽然它是大多数现代CPU上的单个指令,但它通常具有高latency
(PowerPC上31个周期 - 不确定x86上是什么)。如果您有其他非依赖性指令可以与除法同时发出,则可以掩埋一些延迟。所以答案在某种程度上取决于你在包含你的鸿沟的循环中有什么样的指令组合和依赖关系(更不用说你正在使用哪个CPU)。
话虽如此,我的直觉是在大多数架构上,鸿沟比日志功能更快。
答案 3 :(得分:1)
我很确定通过任何算法进行日志计算都会比FP分区更加昂贵。
当然,唯一可以确定的方法是对其进行编码并测量代码的性能。从您的描述中可以看出,实现这两个版本并不是太难以并排尝试。