对于求多项式
朴素的做法是:
double poly0(double a[], double x, long degree) {
long i;
double result = a[0];
double xpwr = x;
for (i = 1; i <= degree; i++) {
result += a[i] * xpwr;
xpwr *= x;
}
return result;
}
这样做需要 n 个加法,2n 个乘法
然后会有人告诉你,可以利用 Horner's method 优化:
double poly1(double a[], double x, long degree) {
long i;
double result = a[degree];
for (i = degree-1; i >= 0; i--)
result = a[i] + x*result;
return result;
}
这样做只需要 n 个加法,n 个乘法
【前方高能预警】
但其实“优化前“比“优化后”还快
因为“优化前”的一个循环里的一个加法和两个乘法是可以并行计算的,三个运算同时进行
而“优化后”的一个循环里的一个加法和一个乘法是不可以并行计算的,加法要等乘法完毕后才能开始
至于为什么,详见 CSAPP 5.7,下面简单说一下
- “优化前”:
两个乘法可以并行是因为CPU里有两个 functional unit 可以进行浮点数乘法
加法可以和乘法并行是因为当前循环的加法可以留待与下一循环的乘法并行 - “优化后”:
很明显加法与乘法是互相依赖的
当前循环的乘法依赖上一循环的加法
当前循环的加法依赖当前循环的乘法
下一循环的乘法又依赖当前循环的加法
所以加法与乘法不能并行