【问题标题】:Why are there too many demand rfo offcore responses /offcore requests?为什么有太多的需求 rfo offcore 响应 /offcore 请求?
【发布时间】:2020-06-08 22:42:37
【问题描述】:

Whiskey Lake i7-8565U/Ubuntu 18.04/HT enabled

考虑以下代码,该代码将恰好位于寄存器 ymm0ymm1 中的一些垃圾数据写入 16 MiB 在由 6400 次迭代组成的循环中静态分配的 WB 内存(因此页面错误影响可以忽略不计):

;rdx = 16MiB >> 3
xor rcx, rcx
store_loop:
vmovdqa [rdi + rcx*8], ymm0
vmovdqa [rdi + rcx*8 + 0x20], ymm1
add rcx, 0x08
cmp rdx, rcx
ja store_loop

使用taskset -c 3 ./bin,我正在通过此示例测量 RFO 请求,结果如下:

Performance counter stats for 'taskset -c 3 ./bin':

     1 695 029 000      L1-dcache-load-misses     # 2325,60% of all L1-dcache hits    (24,93%)
        72 885 527      L1-dcache-loads                                               (24,99%)
     3 411 237 144      L1-dcache-stores                                              (25,05%)
       946 374 671      l2_rqsts.all_rfo                                              (25,11%)
       451 047 123      l2_rqsts.rfo_hit                                              (25,15%)
       495 868 337      l2_rqsts.rfo_miss                                             (25,15%)
     2 367 931 179      l2_rqsts.all_pf                                               (25,14%)
       568 168 558      l2_rqsts.pf_hit                                               (25,08%)
     1 785 300 075      l2_rqsts.pf_miss                                              (25,02%)
     1 217 663 928      offcore_requests.demand_rfo                                     (24,96%)
     1 963 262 031      offcore_response.demand_rfo.any_response                                     (24,91%)
           108 536      dTLB-load-misses          #    0,20% of all dTLB cache hits   (24,91%)
        55 540 014      dTLB-loads                                                    (24,91%)
        26 310 618      dTLB-store-misses                                             (24,91%)
     3 412 849 640      dTLB-stores                                                   (24,91%)
    27 265 942 916      cycles                                                        (24,91%)

       6,681218065 seconds time elapsed

       6,584426000 seconds user
       0,096006000 seconds sys

l2_rqsts.all_rfo的描述是

统计对 L2 的 RFO(读取所有权)请求总数 缓存。 L2 RFO 请求包括 L1D 需求 RFO 未命中以及 L1D RFO 预取。

建议 DCU 可以进行某种 RFO 预取。从Intel Optimization Manual/2.6.2.4对DCU的描述看不清楚:

数据缓存单元 (DCU) 预取器 — 此预取器,也称为 流式预取器,由对非常的上升访问触发 最近加载的数据。处理器假定此访问是一部分 流式算法并自动获取下一行。

所以我猜 DCU 遵循“访问类型”:如果是 RFO,那么 DCU 会进行 RFO 预取。

所有这些 RFO 预取都应该与需求 RFO 一起进入 L2,并且只有其中一些 (l2_rqsts.rfo_miss) 应该进入非核心。 offcore_requests.demand_rfo 只计算需求 rfo,但 l2_rqsts.rfo_miss 计算所有 rfo(需求 + dcu prefectch),这意味着不等式 offcore_requests.demand_rfo < l2_rqsts.rfo_miss 应该被保留。

问题1:为什么l2_rqsts.rfo_missoffcore_requests.demand_rfo少很多(甚至l2_rqsts.all_rfooffcore_requests.demand_rfo少)

我预计 offcore_requests.demand_rfo 的需求可以与 offcore_response.demand_rfo.any_response 匹配,因此这些核心 PMU 事件的数量应该大致相等

问题 2: 为什么 offcore_response.demand_rfo.any_response 几乎是 offcore_requests.demand_rfo 的 1.5 倍?

我猜 L2-streamer 也做了一些 RFO 预取,但无论如何它不应该计入 offcore_requests.demand_rfo


UPD

$ sudo rdmsr -p 3 0x1A4
1

L2-Streamer 关闭

 Performance counter stats for 'taskset -c 3 ./bin':

     1 672 633 985      L1-dcache-load-misses     # 2272,75% of all L1-dcache hits    (24,96%)
        73 595 056      L1-dcache-loads                                               (25,00%)
     3 409 928 481      L1-dcache-stores                                              (25,00%)
     1 593 190 436      l2_rqsts.all_rfo                                              (25,04%)
        16 582 758      l2_rqsts.rfo_hit                                              (25,07%)
     1 579 107 608      l2_rqsts.rfo_miss                                             (25,07%)
       124 294 129      l2_rqsts.all_pf                                               (25,07%)
        22 674 837      l2_rqsts.pf_hit                                               (25,07%)
       102 019 160      l2_rqsts.pf_miss                                              (25,07%)
     1 661 232 864      offcore_requests.demand_rfo                                     (25,02%)
     3 287 688 173      offcore_response.demand_rfo.any_response                                     (24,98%)
           139 247      dTLB-load-misses          #    0,25% of all dTLB cache hits   (24,94%)
        56 823 458      dTLB-loads                                                    (24,90%)
        26 343 286      dTLB-store-misses                                             (24,90%)
     3 384 264 241      dTLB-stores                                                   (24,94%)
    37 782 766 410      cycles                                                        (24,94%)

       9,320791474 seconds time elapsed

       9,213383000 seconds user
       0,099928000 seconds sys

可以看出offcore_requests.demand_rfo 更接近l2_rqsts.rfo_miss,但仍然存在一些差异。在OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD 的英特尔文档中,我发现了以下内容:

注意:提升为 Demand 的预取将从提升中计算 点。

所以我的猜测是 L2 预取被提升为 Demand 并计入 Demand 非核心请求。但它并没有解释offcore_response.demand_rfo.any_responseoffcore_requests.demand_rfo 之间的区别,现在几乎是两倍:

offcore_requests.demand_rfo 1 661 232 864

offcore_response.demand_rfo.any_response 3 287 688 173


UPD:

$ sudo rdmsr -p 3 0x1A4
3

所有 L2 预取器关闭

 Performance counter stats for 'taskset -c 3 ./bin':

     1 686 560 752      L1-dcache-load-misses     # 2138,14% of all L1-dcache hits    (23,44%)
        78 879 830      L1-dcache-loads                                               (23,48%)
     3 409 552 015      L1-dcache-stores                                              (23,53%)
     1 670 187 931      l2_rqsts.all_rfo                                              (23,56%)
            15 674      l2_rqsts.rfo_hit                                              (23,59%)
     1 676 538 346      l2_rqsts.rfo_miss                                             (23,58%)
           156 206      l2_rqsts.all_pf                                               (23,59%)
            14 436      l2_rqsts.pf_hit                                               (23,59%)
           173 163      l2_rqsts.pf_miss                                              (23,59%)
     1 671 606 174      offcore_requests.demand_rfo                                     (23,59%)
     3 301 546 970      offcore_response.demand_rfo.any_response                                     (23,59%)
           140 335      dTLB-load-misses          #    0,21% of all dTLB cache hits   (23,57%)
        68 010 546      dTLB-loads                                                    (23,53%)
        26 329 766      dTLB-store-misses                                             (23,49%)
     3 429 416 286      dTLB-stores                                                   (23,45%)
    39 462 328 435      cycles                                                        (23,42%)

       9,699770319 seconds time elapsed

       9,596304000 seconds user
       0,099961000 seconds sys

现在对 l2 的预取请求总数(来自所有预取器)是 156 206 l2_rqsts.all_pf


UPD:

$ sudo rdmsr -p 3 0x1A4
7

̶A̶l̶l̶̶p̶r̶e̶f̶e̶t̶c̶h̶e̶r̶s̶̶t̶u̶r̶n̶e̶d̶̶o̶f̶f̶.̶ 仅启用 IP 预取器

 Performance counter stats for 'taskset -c 3 ./bin':

     1 672 643 256      L1-dcache-load-misses     # 1893,36% of all L1-dcache hits    (24,92%)
        88 342 382      L1-dcache-loads                                               (24,96%)
     3 411 575 868      L1-dcache-stores                                              (25,00%)
     1 672 628 218      l2_rqsts.all_rfo                                              (25,04%)
            10 585      l2_rqsts.rfo_hit                                              (25,04%)
     1 684 510 576      l2_rqsts.rfo_miss                                             (25,04%)
            10 042      l2_rqsts.all_pf                                               (25,04%)
             4 368      l2_rqsts.pf_hit                                               (25,05%)
             9 135      l2_rqsts.pf_miss                                              (25,05%)
     1 684 136 160      offcore_requests.demand_rfo                                     (25,05%)
     3 316 673 543      offcore_response.demand_rfo.any_response                                     (25,05%)
           133 322      dTLB-load-misses          #    0,21% of all dTLB cache hits   (25,03%)
        64 283 883      dTLB-loads                                                    (24,99%)
        26 195 527      dTLB-store-misses                                             (24,95%)
     3 392 779 428      dTLB-stores                                                   (24,91%)
    39 627 346 050      cycles                                                        (24,88%)

       9,710779347 seconds time elapsed

       9,610209000 seconds user
       0,099981000 seconds sys

UPD:

$ sudo rdmsr -p 3 0x1A4
f

禁用所有预取器

 Performance counter stats for 'taskset -c 3 ./bin':

     1 695 710 457      L1-dcache-load-misses     # 2052,21% of all L1-dcache hits    (23,47%)
        82 628 503      L1-dcache-loads                                               (23,47%)
     3 429 579 614      L1-dcache-stores                                              (23,47%)
     1 682 110 906      l2_rqsts.all_rfo                                              (23,51%)
            12 315      l2_rqsts.rfo_hit                                              (23,55%)
     1 672 591 830      l2_rqsts.rfo_miss                                             (23,55%)
                 0      l2_rqsts.all_pf                                               (23,55%)
                 0      l2_rqsts.pf_hit                                               (23,55%)
                12      l2_rqsts.pf_miss                                              (23,55%)
     1 662 163 396      offcore_requests.demand_rfo                                     (23,55%)
     3 282 743 626      offcore_response.demand_rfo.any_response                                     (23,55%)
           126 739      dTLB-load-misses          #    0,21% of all dTLB cache hits   (23,55%)
        59 790 090      dTLB-loads                                                    (23,55%)
        26 373 257      dTLB-store-misses                                             (23,55%)
     3 426 860 516      dTLB-stores                                                   (23,55%)
    38 282 401 051      cycles                                                        (23,51%)

       9,377335173 seconds time elapsed

       9,281050000 seconds user
       0,096010000 seconds sys

即使预取器被禁用 perf12 报告为 pf_miss(可在具有不同值的不同运行中重现)。这可能是计数错误。 1 672 591 830 l2_rqsts.rfo_miss 的值也比1 662 163 396 offcore_requests.demand_rfo 稍大,我也倾向于将其解释为计数错误。


假设: DCU RFO Prefetch 缺少 L2 和脱离核心计入 offcore_requests.demand_rfo

如果 L2-streamer 关闭,假设有效:102 019 160 l2_rqsts.pf_miss + 1 579 107 608 l2_rqsts.rfo_miss = 1 681 126 768; 1 661 232 864 offcore_requests.demand_rfo

如果所有预取器都关闭,该假设也有效:1 684 510 576 l2_rqsts.rfo_miss; 1 684 136 160 offcore_requests.

在所有 PF 关闭的情况下,L1-dcache-load-misses 大约等于 l2_rqsts.rfo_miss 反过来等于 offcore_requests.demand_rfo

我仍然不知道为什么offcore_response.demand_rfo.any_responseoffcore_requests.demand_rfo 具有更大的价值

【问题讨论】:

  • 应该有多少个需求 RFO?我无法从显示的代码中分辨出来,因为我不知道 rdx 中的内容以及正在访问多少不同的物理页面。你预计有多少人会在 L1 中错过?你只计算用户模式事件吗?正在使用perf?如果是,那么这些计数是否包括任何其他重要的代码片段。 HT被禁用了吗?您可以删除 offcore_requests_outstanding.demand_rfol2_rqsts.all_demand_data_rd 以避免在禁用 HT 的情况下进行多路复用。多次重复实验并显示每个事件的标准偏差。

标签: assembly x86 x86-64 cpu-cache rfo


【解决方案1】:

对于问题 1,答案(至少在 Skylake 上,但对于 Whiskey Lake 很可能是相同的)是 L2 RFO 事件在它们由预取启动时不计算在内:不会在触发预取时,甚至当 RFO 后来在 L2 中命中或未命中时也不会。您可以通过设置事件的预取位(在 umask 中设置 0x10)来计算这些事件,在这种情况下,您会看到重复计数为 described here

您看到的事件是 L2 预取器没有帮助的 RFO 的一个随机子集。核心外的计数器显然没有这样的问题:即使请求是由预取发起的,当需求命中正在进行的请求时,它也可以提升为需求请求。

您可以找到更多详细信息here,并且您应该仔细检查您的 perf 版本使用了哪些事件,因为英特尔更改了最后一个链接中描述的事件定义。

【讨论】:

  • 我假设您的意思是0x24 事件编号。对于我的 WhL DisplayFamily_DisplayModel06_8e,唯一指定的事件是 0x21。因此,单独使用0x200x01 通常是无证的。可能我错过了一些东西,但事件掩码 0x010x20 被明确记录为 SnB (Table 19-15/ Intel Manual Vol. 3) 和 IvB (Table 19-17/ Intel Manual Vol. 3),但不是 Haswell 或更高版本。
  • 不幸的是 umask 0x10 在我的 cpu 上计数零事件。
  • @Antario - 您需要将 umask 0x10 与其他位组合以获得有意义的结果。当然,这都是“未记录的”,这就是第二个链接中的内容的重点,它解释了事件的实际运作方式。
  • 这是在 SKL 上,可能是 6_5E,我稍后会检查。
  • 是的,它是 6_5E。无论文档如何,我都希望 Whiskey Lake 在 PMU 功能上几乎相同。
【解决方案2】:

在我看来,循环正在写入 2^18 个缓存行,并且有一个外部循环(问题中未显示)执行内部循环(即所示的那个)6400 次。因此,预期的需求 RFO 总数为 2^18*6400 = 1,677,721,600,预期的已停用存储指令数为 1677721600*2 = 3,355,443,200。实测L1-dcache-stores门店数量约为34.10亿,比预期多出约5500万。这个事件计数应该是准确的,所以我认为问题中没有显示其他影响事件计数的代码。负载事件计数还表明有许多负载来自某个地方,这对事件的计数有显着影响l2_rqsts.all_pfl2_rqsts.pf_hitl2_rqsts.pf_miss。我已经在我的评论中询问了测量中是否包含任何其他重要的代码。

从启用所有预取器的第一个实验的结果来看,l2_rqsts.rfo_hit + offcore_requests.demand_rfo 加起来的数量几乎等于需求 RFO 的预期数量。 L2 流媒体实际上可以预取 RFO,如英特尔优化手册中所述,该手册解释了如何存在 l2_rqsts.rfo_hit。我不知道为什么l2_rqsts.rfo_miss 不等于offcore_requests.demand_rfo。我认为事件offcore_requests.demand_rfo 是准确的。尝试仅禁用 L1D 预取器并保持 L2 预取器启用,并查看执行时间是否增加。如果 L1D 预取器实际上发送了大量的 RFO,则 L1D 中应该有足够的写入命中,这样它就会对性能产生影响。

禁用 L2 流媒体的第二次实验的结果非常接近预期。 l2_rqsts.rfo_hit 非常小,l2_rqsts.all_rfo 几乎等于 offcore_requests.demand_rfo,这等于需求 RFO 的预期数量。这提供了 L1D 预取器不预取 RFO 的实验证据。在这种情况下,l2_rqsts.all_pf 应该为零,因为两个 L2 预取器都已禁用。

在上一个实验中,您只关闭了四个数据缓存预取器中的三个;你错过了 DCU IP 预取器。在这种情况下,2_rqsts.all_rfo 的计数更接近例外情况。尝试禁用 DCU IP 预取器,看看l2_rqsts.rfo_hit(可能还有l2_rqsts.all_pf)是否变为零。

Erratum 058 在您的处理器的规格更新文档中说offcore_response.demand_rfo.any_response 可能会多计,可以使用offcore_requests.demand_rfo 代替。这解释了为什么offcore_response.demand_rfo.any_response 大于所有实验中的预期值,也表明offcore_requests.demand_rfo 是可靠的。

【讨论】:

  • L2 流媒体实际上可以预取英特尔优化手册中记录的 RFO 我想您的意思是来自 3.7.3 的以下文本:DPL 也可以通过以下方式触发读取所有权 (RFO) 操作。 L2 Streamer 也可以由 L2 缓存未命中的 DPL 请求触发。如果我错了,请纠正我。
  • @St.Antario 我指的是第 2.5.5.4 节,其中提到了 L2 流送器,受监控的读取请求包括由加载和存储操作发起的 L1 DCache 请求...尽管本节属于 Sandy Bridge(第 2.5 节),但此特定声明也适用于后来的微体系结构。实际上,第 2.5 节的大部分内容适用于后来的微架构。我还没有在 Ice Lake 处理器上进行过实验,但我没有看到任何迹象表明任何数据预取器都发生了显着变化/改进,除了变得更加激进。
猜你喜欢
  • 2018-07-13
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多