【发布时间】:2019-05-02 16:46:39
【问题描述】:
我正在尝试优化 sin/cos 逼近函数。它的核心是一个简单的Horner scheme,由一堆乘法和加法组成。编译器是 VS2017 的 MSVC,处理器是 Intel Xeon E5-1650,超线程开启(但如果关闭,观察结果基本相同)。
使用 Intel 的 VTune Amplifier 2019,我在随机双精度数(-2 pi 和 2 pi 之间)上运行函数超过 1 分钟获得了分析结果(当然是发布版本),大约 40% 的时钟用于下面显示的部分(其余部分是范围缩小 + 测试工具)。但是,我无法理解 VTune 提供给我的微架构指标:
这是内联的相应 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,但并不是每个必须运行此(单个)二进制文件的平台都提供它们。目前我不打算进行运行时调度。
【问题讨论】:
-
不良推测指标测量值非常小,因此并不重要。 DSB 覆盖率非常低,但您似乎没有前端档位,所以没关系。但是,您似乎有很多灰色数据,这意味着 VTune 对它们没有信心,因此它们并不真正可靠。您能否提供有关您使用的 VTune 设置的更多详细信息?你能重现这些结果吗?从您显示的图像中我不清楚瓶颈在哪里,因为一切看起来都很好。
-
关于您的第一个问题,如果在该指令中未采集样本,则不会将任何数据归因于该指令,因此您会看到空单元格。关于你的第三个问题,我最好的猜测是这是由于事件多路复用。关于您的第四个问题,可以折叠前端绑定列,以便我可以查看它是否实际上是前端绑定。我还需要查看后端绑定列
-
关于您的第二个问题,好吧,您似乎有两条长依赖链:一条从
movsd xmm1, [rip+0x38de]开始,一条从movsd xmm1, [rip+0x386a]开始。虽然这两个链可以并行执行,但前提是它们是交错的,这可以通过使它们使用不同的寄存器来完成(例如xmm2)。 -
@HadiBrais 感谢到目前为止的 cmets!关于不良投机:VTune 告诉我,我因不良投机而损失了大约 13%。我不会担心这一点,但它几乎完全源于那个(无推测?)部分。结果非常具有可重复性。我已经用“允许多次运行”进行了另一次会议,以消除所有多路复用问题,结果几乎相同——第二条链同样缺乏数据,CPI、退休、前端和不良推测中的分布相同(部分更糟)列。
-
13% 是很多。但是你分享的图片中的错误推测指标加起来不到 13%,所以这一定来自其他地方。
标签: performance x86 micro-optimization intel-vtune intel-pmu