bbt*_*trb 1 c c++ optimization numeric
我正在自动生成C代码来计算大型表达式,并试图用简单的例子弄清楚在单独的变量中预定义某些子部分是否有意义.
举个简单的例子,假设我们计算了一些形式:
#include <cmath>
double test(double x, double y) {
const double c[9][9] = { ... }; // constants properly initialized, irrelevant
double expr = c[0][0]*x*y
+ c[1][0]*pow(x,2)*y + ... + c[8][0]*pow(x,9)*y
+ c[1][1]*pow(x,2)*pow(y,2) + ... + c[8][1]*pow(x,9)*pow(y,2)
+ ...
Run Code Online (Sandbox Code Playgroud)
所有c [i] [j]正确初始化.实际上,这些表达式包含数以千万计的乘法和加法.
现在提出一个同事 - 减少对pow()的调用次数并缓存表达式中经常需要的值 - 在单独的变量中定义x和y的每个幂,这没什么大不了的,因为代码是自动的无论如何生成,像这样:
double xp2 = pow(x,2);
double xp3 = pow(x,3);
double xp4 = pow(x,4);
// ...
// same for pow(y,n)
Run Code Online (Sandbox Code Playgroud)
但是,我认为这是不必要的,因为编译器应该处理这些优化.
不幸的是,我没有阅读和解释汇编的经验,但我想我看到所有对pow()的调用都被优化了,这是对的吗?此外,编译器是否缓存pow(x,2),pow(x,3)等的值?
提前感谢您的意见!
使用pow
整数参数...哎哟!pow
针对浮点参数的一般情况调整了典型的实现,这就是为什么写入通常会慢一些的原因
pow(x, 2) ( = exp(2 * log(x)) )
Run Code Online (Sandbox Code Playgroud)
比
x * x
Run Code Online (Sandbox Code Playgroud)
我在这里声明的是非常依赖于编译器.一方面,一些编译器可能甚至不知道pow(x, 2)
将给出给定的相同值x
(毕竟,extern函数pow
可能有副作用),因此您无法保证将消除公共子表达式.的pow
功能,在某些(许多?)平台/工具链,由一个库提供的编译器没有控制到.
但是,在其他实现中,编译器可能会将这些pow
调用转换为乘法,或者至少转换为内部函数,而内部函数又可以专门用于整数指数.你的里程会有所不同.
我要做的第一件事就是pow
通过乘法来替换调用.对于较大的指数,您也可以这样做,例如.
double x2 = x * x;
double x3 = x * x2;
double x4 = x2 * x2;
Run Code Online (Sandbox Code Playgroud)
注意(对@Stephen Canon的信用)进行重复乘法(使用上述快速取幂方案)将引入舍入误差,其幅度与乘法的数量成比例(即O(对数指数)).此错误通常是可以容忍的,但pow
保证在一个最小精度单位内的准确性.
归档时间: |
|
查看次数: |
805 次 |
最近记录: |