首页 文章

VTune分析显示没有关于多态函数的分支预测的度量标准?

提问于
浏览
3

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

我使用VTune描述了这两种设计 . 高级摘要数据似乎有意义 - 多态设计具有更高的“分支误预测”率,更高的CPI和更高的“ICache未命中率”,而不是使用IF语句实现的非多态版本 .

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

object->virtualFunction();

这被称为数百万次(子类型每次都改变) . 由于分支目标误预测/指令未命中,我期待多态设计变慢 . 如上所述,VTune“摘要”选项卡似乎证实了这一点 . 但是,当我查看源代码行旁边的指标时,除了以下内容之外绝对没有指标:

  • 填充管道插槽总数 - >退役 - >一般退休

  • 填充管道槽自我 - >退休 - >一般退休

  • 未填充的管道插槽总数 - >前端绑定 - >前端带宽 - >前端带宽MITE

  • 未填充的管道插槽自我 - >前端绑定 - >前端带宽 - >前端带宽MITE

没有分支预测列有数据,指令高速缓存未命中列?

有人可以评论这是否合情合理?对我来说,它不是 - 如果分支目标将不断改变每条消息的多行代码行,怎么会没有分支错误预测或指令缓存未命中统计?

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

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

2 回答

  • 2

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

    有人可以评论这是否合情合理?对我来说,它不是 - 如果分支目标将不断改变每条消息的多行代码行,怎么会没有分支错误预测或指令缓存未命中统计?这不能归因于编译器优化/内联,因为编译器不知道要优化的对象的子类型 .

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

    您可以观看this Eric Brumer's talk了解更多详情,从22:30开始,他谈到间接呼叫优化 .

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

    我建议查看该函数调用的反汇编 . 它是否真的使用vtable指针间接跳转到代码,或者它是否通过一些优化避免vtable跳转 .

    如果调用没有被编译器优化,那么CPU仍有一些推测方法,挖掘Branch Target Buffer . 例如,如果在相同类型的对象的紧密循环中调用此函数,那么它是否为虚拟可能无关紧要,其地址可能会被预测...

    HTH .

  • 1

    您没有在指令本身上看到分支错误预测,因为样本将在分支之后的下一条指令上“聚合” .

    所有非精确事件都是如此(最后没有 _PS ) . 人们可以通过检查常规代码配置文件轻松找到它 . 例如,有更高的可能性,人们会发现在一个简单的 add 上有更多的 CPU_CLK_UNHALTED 样本,而不是在 add 之前的重 imul 上 .

    为了查看事件发生的"exact"指令,您必须使用精确的事件,例如 BR_MISP_RETURED.ALL_BRANCHES_PS .

    我不是100%肯定这个“问题”的本质,我知道应该可以修复它,但由于某种原因,VTune采样驱动程序的人不想这样做 . 我知道有一个人在过去的6年里一直在与这个问题作斗争,我将其纳入其中帐户每次检查asm VTune配置文件:)

    PS . 关于虚拟功能的原始测试 . 我也测试了它,它确实产生了很多分支错误预测 . 对于函数指针也是如此 . 修复它的一种方法是使用模板类,如果可能的话 .

相关问题