我想知道是否有以下两种方法之间在速度上有什么区别
#include<math.h>
#include<iostream>
using namespace std;
int main()
{
float k=7;
float b=4;
cout<<(float)k/b<<" "<<endl;
cout<<(float)(k*powf(b,-1))<<" "<<endl;
return 0;
}
- 琐碎diivision
k/b
- 使用乘法
k*b^(-1)
我认为,在第二个方法,没有具体分工过程。 所以我觉得第二个是快。 我对吗?
计算b ^( - 1)是不平凡的,并且有时会(尽管并不总是)由优化器转换为1 / B。 正如很多,优化器可以切换*b^(-1)
与/b
。 这可能是硬件相关的(甚至可能是数依赖性,如果数字在编译时已知)。
如果你想测试它,把每一个在运行很多次(不打印任何内容到屏幕)的循环,并且每个时间执行。
另请注意,在某些情况下,这两个方法会给您带来稍有不同的结果,如果你有兴趣在精确的计算。
机会是非常好的,你错了。 即使编译器可以生成powf
作为内在的(即,为其生成内嵌代码),N -1相当于1 / N,所以你只是做了分工更迂回的方式。 如果提高到一个功率为做除法更快的方法,编译器可能会产生已代码做这种方式。
在另一方面,如果你使用相同的分母做了很多次,你可以通过转动圈状收获:
for (int i=0; i<some_size; i++)
somearray[i] /= denom;
成:
double scale = 1.0/denom;
for (int i=0; i<some_size; i++)
somearray[i] *= scale;
当然,编译器可能是足够聪明,要做到这一点为好,但至少有这样的事情,你在做什么代表的是一种改进像样的机会-唯一的问题是,是否编译器已经这样做了它给你的。
你就应该剖析两个版本,并检查其中一个的速度更快,但我几乎准备吃我的帽子,如果是第二个,有以下几个原因:
-
powf
是一个普遍的功能是为指数参数的典型值很慢。 即使是最优化处理的情况下-1
特别,仍然会有if
S,等检查这种特殊情况下,这将增加开销来计算。 - 根据执行情况,
powf
可能不被内联,你会招致函数调用的成本。 - 如果
k*(1.0/b)
比真快k/b
,那么编译器将优化后者向前已经(特别是当指定的编译器标志,以便快速,但不一定完全符合IEEE标准的,浮点运算。 )
底线是,现代编译器在执行microoptimizations非常好; 除非分析和拆解显示的确凿证据为编译器做一些低效我做梦也不会想到tryings“招数”像这样的。
速度总是取决于你的编译器如何优化。 因此,一个可靠的答案,只能通过测量发现。
然而,第二种方法意味着比第一个电话。 因此,我想第一个会更快。
正如其他人所指出的,轮廓。 在计算机科学,分工可以通过重复减法来实现。 这可能比通过逆乘快。
我相信,因为逆必须首先计算,然后乘执行的部门将是比倒数乘以速度更快。 因此,虽然分割执行减法时,另一种方法是确定逆。 逆计算,多个移位后并增加(乘)必须执行。
请参见上除法算法维基百科文章
我X86-64的机器上使用GCC -02,K / B转换为一条指令:
divss xmm0, xmm1
在“函数powf”的方式结果如下:
movss xmm2, DWORD PTR .LC0[rip]
divss xmm2, xmm1
mulss xmm2, xmm0
movaps xmm0, xmm2
其中.LC0是1065353216,或1.0F。
因此,它似乎对我来说,至少在x86-64的机器,是常见的今天,K / b为快。