当前位置: 首页 > 知识库问答 >
问题:

VTune 分析未显示多态函数分支预测的指标?

糜鸿风
2023-03-14

我正在分析处理数百万条消息的两种设计之间的差异。一种设计使用多态,另一种不使用——每个消息都将由多态子类型表示。

我已经使用 VTune 分析了这两种设计。高级摘要数据似乎很有意义 - 与使用IF语句实现的非多态版本相比,多态设计具有更高的“分支误判”率,更高的CPI和更高的“ICache未命中”率。

多态设计有一行源代码,如下所示:

object->virtualFunction();

这被称为数百万次(其中子类型每次都改变)。由于分支目标预测失误/指令未命中,我预计多态设计会更慢。如上所述,VTune“摘要”选项卡似乎证实了这一点。然而,当我转到源代码行旁边的度量时,绝对没有度量,除了:

  • 填充管道槽总数-

没有分支预测列具有数据,指令缓存也不会丢失列??

有人能评论一下这是否明智吗?对我来说,它没有——对于一行多态代码,分支目标将在每条消息中不断变化,怎么可能没有分支错误预测或指令缓存丢失统计?

这不能是由于编译器优化/内联,因为编译器不知道要优化的对象的子类型。

应如何使用 VTune 分析多态性的开销?

共有2个答案

莘翰采
2023-03-14

您不会在指令本身上看到分支预测失误,因为样本将在分支之后的下一条指令上“聚合”。

适用于所有非精确事件(末尾没有_PS)。人们可能很容易通过检查常规代码配置文件来找到它。例如,在更高的可能性下,人们会发现在简单的添加物上有更多的CPU_CLK_UNHALTED样本,而不是在添加之前出现的重imul上。

为了在事件发生的地方看到“精确的”指令,你必须使用精确的事件,例如< code > BR _ MISP _返回。ALL _ branch _ PS 。

我不是100%确定这个“问题”的真正性质,我知道应该可以解决它,但出于某种原因VTune采样驱动程序的人不想这样做。我认识一个人,他在过去6年里一直在与这个问题作斗争,每次我检查asm VTune配置文件时,我都会考虑到这一点:)

PS。关于虚拟函数的原始测试。我也测试过,它确实产生了很多分支预测失误。函数指针也是如此。解决这个问题的一个方法是,如果可能的话,使用模板类。

曹和正
2023-03-14

我将尝试回答问题的第一部分:

有人能评论一下这是否明智吗?对我来说,它没有——对于一行多态代码,分支目标将在每条消息中不断变化,怎么可能没有分支错误预测或指令缓存丢失统计?

这不能是由于编译器优化/内联,因为编译器不知道要优化的对象的子类型。

实际上,编译器有一种方法可以内联调用虚拟函数,这是一种有趣的技巧,当我了解到这一点时,我感到惊讶。

您可以观看Eric Brumer的演讲以了解更多详细信息,从22:30分钟开始,他谈到了间接呼叫优化。

基本上,编译器不是向该虚函数指针发出简单的跳转指令,而是首先添加一些比较,并且对于一些已知的指针值预测调用的特定虚函数,然后该调用可以内联到该分支中。在这种情况下,不可预测的指针值跳转变成了一个简单的比较分支预测,而现代CPU擅长于此。因此,如果大多数调用将进入相同的特定虚函数实现,您可能会看到良好的预测数和低指令缓存未命中数。

我建议研究该函数调用的反汇编。它是使用vtable指针间接跳转到代码,还是通过一些优化避免vtable跳转。

如果编译器未优化调用,则 CPU 仍可通过某种方式进行推测,请深入研究分支目标缓冲区。例如,如果在同一类型的对象上以紧密循环方式调用此函数,则无论它是否是虚拟的,都可以预测其地址...

HTH

 类似资料:
  • 如果语句更多地依赖于分支预测,而v表查找更多地依赖分支目标预测,那么

  • 分支目标预测(BTP)与分支预测(BP)不同。我知道BTP会找到分支将跳转到的位置,而BP只是决定可能采取哪个分支。 BTP依赖BP吗,如果BTP不使用BP来预测哪个分支被采用,它怎么可能知道分支的目标呢? 我不明白为什么会有这么大的差异?一旦分支被预测为被占用,找到目标并不像读取指令中的地址一样简单吗?

  • 编辑:我的困惑出现了,因为通过预测哪个分支,你肯定也在有效地进行目标预测?? 这个问题与我关于这个主题的第一个问题有内在联系: 分支预测与分支目标预测 无限循环 语句 或语句 语句的“then”子句结尾(跳过子句) 非虚函数调用 从函数返回 虚函数调用 函数指针调用 语句(如果编译为跳转表) 语句 语句(如果编译成一系列语句) 循环条件测试 和运算符 三元运算符 null 如果我有以下代码: (B

  • Sonarqube服务器7.0版(构建36138) Sonarqube分支插件7.0(构建413) Sonarqube已经建立了一个主分支机构。 作为Jenkins构建作业的一部分,我们执行以下命令: 其中BRANCH设置为我们在Jenkins构建的分支名称。 [信息]分支名称:发展,类型:短命 这使我相信,发展并没有被认为是一个长期存在的分支。 2)在问题选项卡中没有输出。只有代码选项卡显示任何

  • 我的代码经常调用具有多个(不可预测的)分支的函数。当我分析时,我发现这是一个小瓶颈,大部分CPU时间用于条件JMP。 考虑以下两个函数,其中原始函数有多个显式分支。 这是一个新函数,我试图在其中删除导致瓶颈的分支。 然而,当我分析新代码时,性能只提高了大约20%,而且调用本身(对mem_funcs数组中的一个func)花费了很长时间。 第二个变量仅仅是一个更隐含的条件吗,因为CPU仍然无法预测将要

  • 我正在阅读Patterson和Hennessy的《计算机组织与设计:硬件/软件接口第5版》第5章中的动态分支预测部分,这时我看到了以下2位预测器状态的图表: 在预测错误两次后,2位预测器应该改变它的预测。但是根据这个图,当我们从左下方的状态开始时,如果机器在分支应该被“采取”时预测“未采取”两次,则到达右上方的预测采取状态。然而,此时机器会将状态更改为右下角的“预测未执行”,即使它错误地预测了分支