是什么导致DTLB_LOAD_MISSES.WALK_ *性能事件发生?

时间:2018-09-29 22:05:14

标签: x86 cpu-architecture tlb intel-pmu

考虑以下循环:

.loop:
    add     rsi, STRIDE    
    mov     eax, dword [rsi]
    dec     ebp
    jg .loop

其中STRIDE是一些非负整数,而rsi包含一个指向bss节中定义的缓冲区的指针。此循环是代码中的唯一循环。也就是说,它不会在循环之前被初始化或触动。在Linux上,缓冲区的所有4K虚拟页面将按需映射到同一物理页面。

我已经为所有可能的跨度(0-8192)运行了此代码。每访问的一页,次要和主要页面错误的度量数量分别分别为1和0。我还测量了该范围内所有跨度的Haswell下列所有性能事件。

  

DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK :在所有TLB级别中均未命中   导致任意页面大小的页面浏览。

     

DTLB_LOAD_MISSES.WALK_COMPLETED_4K :由于需求而完成的页面浏览   导致4K分页浏览在任何TLB级别下的加载未命中。

     

DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M :由于以下原因完成了页面浏览:   在任何TLB级别中,导致2M / 4M页面漫游的需求负载未命中。

     

DTLB_LOAD_MISSES.WALK_COMPLETED_1G :所有TLB级别的加载未命中原因   完成的页面浏览。 (1G)。

     

DTLB_LOAD_MISSES.WALK_COMPLETED :已完成的页面可在任何   由于未满足需求负载而导致页面大小

对于所有大步幅,大页面的两个计数器都为零。如下图所示,其他三个计数器很有趣。

enter image description here

在大多数情况下,MISS_CAUSES_A_WALK事件每访问一页都会发生5次,WALK_COMPLETED_4KWALK_COMPLETED事件每访问一页都会发生4次。这意味着所有完成的页面遍历都是针对4K页面。但是,没有完成第五步。为什么每页有那么多的页面浏览?是什么导致这些页面漫游?也许当页面遍历触发页面错误时,在处理完该错误之后,还会有另一个页面遍历,因此这可以算作两次已完成的页面遍历。但是,为什么会有4个完整的页面漫游和一个显然被取消的漫游?请注意,Haswell上只有一个页面漫游器(而Skylake上只有两个)。

我意识到有一个TLB预取器似乎只能预取此thread中讨论的下一页。同样根据该线程,预取程序遍历似乎没有被计为MISS_CAUSES_A_WALKWALK_COMPLETED_4K事件。

如上图所示,还有一种特殊的小步幅模式。另外,在步幅220附近有一个非常奇怪的图案(尖峰)。我能够多次重现这些图案。下图放大了该奇怪的图案,因此您可以清楚地看到它。这些模式的原因是什么?

enter image description here

我还尝试了以下配置:

  • 在执行循环之前以某种模式提交虚拟页面。我尝试了4种模式:(1)从缓冲区的第一个虚拟页面开始交替提交虚拟页面,(2)从缓冲区的第二个虚拟页面开始交替提交虚拟页面,(3)提交页面的前半部分。缓冲区,以及(4)提交所有页面。
  • 呼叫mlockall
  • 关闭L1和L2硬件预取器
  • 使用预取指令代替需求负载。

我得出以下结论:

  • 当由于需求负载而导致页面漫游导致页面错误时,会发生DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK事件,但不会发生DTLB_LOAD_MISSES.WALK_COMPLETED_4K。当由于软件预取而导致页面漫游导致页面错误时,将发生DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK事件和DTLB_LOAD_MISSES.WALK_COMPLETED_4K事件。当然,在预取的情况下,不会触发页面错误。
  • 硬件预取器确实会影响页面漫游事件,但是很难看到任何模式。
  • 页面遍历事件的数量似乎取决于需求负载的步幅。特别是,对于所有配置,跨度在128-256之间会导致事件计数最大。这很奇怪。这个范围有什么特别之处?
  • 即使在所有页面都在循环之前提交(零错误)的简单情况下,不同步幅的事件计数仍然存在一些不平凡的变化(尽管不重要,每个TLB丢失大约1步)。相反,当所有页面都出现故障时,差异也很小,但计数却大不相同(请参见第一个图表)。我不确定是否可以由此得出结论,下一页预取程序不会影响页面漫游事件。
  • mlockall似乎对事件计数没有任何重大影响。
  • DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK似乎总是比DTLB_LOAD_MISSES.WALK_COMPLETED_4K大。
  • 所有PAGE_WALKER_LOADS.*事件计数的总和始终大于页面浏览的数量。我不清楚它们之间的关系。
  • 由于我不知道如何解释分页计数,因此很难解释DTLB_LOAD_MISSES.WALK_DURATION。但是似乎任何页面走动都至少需要14个周期。除此之外,我没有看到关于PAGE_WALKER_LOADS.*的模式。

@BeeOnRope建议将LFENCE放入循环中,并将其展开零次或多次,以更好地了解投机,无序执行对事件计数的影响。下图显示了结果。当循环展开0-63次(单次迭代中有1-64个添加/加载指令对)时,每一行代表一个特定的加载步幅。 y轴每页标准化。访问的页面数与次要的页面错误数相同。

enter image description here

enter image description here

我还进行了没有LFENCE但展开度不同的实验。我没有为这些图表制作图表,但下面将讨论主要区别。

我们可以得出以下结论:

  • 当负载跨度小于128个字节时,MISS_CAUSES_A_WALKWALK_COMPLETED_4K在不同的展开度上会显示出较大的变化。大步幅具有平滑的曲线,其中MISS_CAUSES_A_WALK收敛到3或5,WALK_COMPLETED_4K收敛到3或4。
  • LFENCE似乎仅在展开度精确为零(即,每次迭代有一个负载)时有所不同。如果没有LFENCE,则结果(如上所述)为每页5 MISS_CAUSES_A_WALK和4 WALK_COMPLETED_4K个事件。使用LFENCE,它们每页都变为3。对于较大的展开度,事件计数平均逐渐增加。当展开度至少为1时(即,每次迭代至少有两个负载),LFENCE基本上没有区别。这意味着,在没有LFENCE的情况下,上面的两个新图图是相同的,除了每次迭代有一个负载时。顺便说一下,只有在展开度为零且没有LFENCE时,才会出现怪异的尖峰。
  • 通常,展开环路会减少已触发和完成的行走的次数,尤其是在展开程度较小时,无论负载跨度如何。在不展开的情况下,LFENCE可以实质上获得相同的效果。展开后,无需使用LFENCE。在任何情况下,使用LFENCE的执行时间都会更长。因此,使用它减少页面浏览量会大大降低性能,而不是提高性能。

0 个答案:

没有答案