练习题5.5 题目如下:
对多项式求值a0+a1x+a2x^2+...+an*x^n。
代码如下:
double poly(double a[], double x, int degree)
{
long int i;
double result = a[0];
double xpwr = x;
for ( i = 1; i <= degree; i++)
{
result += a[i] * xpwr;
xpwr = x * xpwr;
}
return result;
}
该题第二问说到,在参考机Core i7上,测量这个函数的CPE等于5.00。
参考答案是这样解释的:限制性能的计算是反复地计算表达式xpwr = x * xpwr。这需要一个双精度浮点数乘法(5个时钟周期),并且直到前一次迭代完成,下一次迭代的计算才能开始。两次连续的迭代之间,对result的更新只需要一个浮点加法(3个时钟周期)。
那我的问题就是,a[i] * xpwr这个代码不应算入对result的更新的时钟周期么?也就是说实际的CPE不应该是5+3么?
我有完全一样的问题,后来找到了网上的一篇文章解释的挺清楚的(https://is.daryl.moe/posts/cs...),下面我用自己的话复述一下,希望能帮到大家。
之前的答案没有解释很让人迷惑的一点,就是
result += a[i] * xpwr
这句话不仅有需要3个周期的加法,里面还有个乘法不能忽略啊,光执行这句话就要8个周期,那一个循环需要的周期数瓶颈难道不是这句话吗?事实上这8个周期是“虚”的,这句话在循环中执行的吞吐量只相当于5个周期,能做到这一点的关键在于,计算这一次的加法可以和计算下一次的乘法同时进行。接下来我把我理解的整个循环过程发生了什么叙述一遍。
第一步,计算
a[i]*xpwr
和xpwr*x
。由于处理器有两个浮点乘单元所以这两个运算被并行处理,5个周期。第二步,计算
result+(上一步算出的a[i]*xpwr)
。这个需要3个周期。等等,这不就8个周期了嘛?但是我们发现,这个第二步的结果不会影响下一轮迭代的第一步的计算,因此我们可以同时计算这一轮的第二步和下一轮的第一步。