我正在尝试优化sin / cos逼近函数。它的核心是一个简单的Horner scheme,它由一堆乘法和加法组成。编译器是VS2017的MSVC,处理器是Intel Xeon E5-1650,超线程已打开(但如果关闭,则观察到的结果基本相同)。
使用Intel的VTune Amplifier 2019,我获得了超过1分钟的随机双打(-2 pi和2 pi之间)运行该函数的性能分析结果(当然是发布版本),其中约40%的时钟花费在所示部分中下方(剩下的是范围缩小+测试装置)。但是,我无法理解VTune为我提供的微体系结构指标:
(内联后,MSVC的源代码行属性非常糟糕。)
这是内联的相应C ++代码:
void stableSinCosApproximation(double x, double* sinApprox, double* cosApprox)
{
double x2 = x * x;
*sinApprox = x * (sinCoeff[7] + x2 * (sinCoeff[6] + x2 * (sinCoeff[5] + x2 * (sinCoeff[4] + x2 * (sinCoeff[3] + x2 * (sinCoeff[2] + x2 * (sinCoeff[1] + x2 * sinCoeff[0])))))));
*cosApprox = (cosCoeff[7] + x2 * (cosCoeff[6] + x2 * (cosCoeff[5] + x2 * (cosCoeff[4] + x2 * (cosCoeff[3] + x2 * (cosCoeff[2] + x2 * (cosCoeff[1] + x2 * cosCoeff[0])))))));
}
显然,程序集清单只有一个连续的指令块。没有跳转(也没有跳转目标),根本没有分支或有条件的执行。但是,这里有多个指标,对于VTune的内置或联机帮助所提供的信息,我无法理解它们的值。
具体问题:
代码的后半部分几乎没有归因,也没有时钟标记。为什么?
上半年CPI不断上升。好的,也许这和上一点是由于归因出了错,但我不明白。
度量标准表明存在错误的推测。但是在扩展该列时,它既不会显示分支预测错误,也不会显示机器清除:
这应该告诉我什么? CPU在这里猜测什么容量?
据称,我也因为前端绑定而失去了很多机会。与不良推测列的相关性是否只是巧合?我应该如何处理这些信息?
优先注意事项:
重新实现这一点的目的是确保跨多个平台(从同一二进制文件)实现一致性。内置的sin / cos函数在不同的机器上可能会有一些ULP的变化,这会破坏结果的可重复性。
是的,我了解FMA,但并非该(单个)二进制文件必须在其上运行的每个平台都提供它们。目前,我不打算进行运行时调度。
最佳答案
您可以从VTune的“自下而上”窗格而不是程序集窗格中显示屏幕截图吗?有趣的是整个功能的特征描述(例如不良推测和前端绑定的值,BR_MISP_RETIRED.ALL_BRANCHES_PS和MACHINE_CLEARS.COUNT个事件的计数)。
关于performance - 矛盾的VTune放大器微体系结构探索结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53559057/