assembly - 为什么对非核心响应/非核心请求的需求过多?

标签 assembly x86 x86-64 cpu-cache

Whiskey Lake i7-8565U/Ubuntu 18.04/HT enabled
考虑下面的代码,它写入了一些碰巧在寄存器 ymm0 中的垃圾数据。和 ymm1在由 6400 次迭代组成的循环中进入 16 MiB 静态分配的 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的说明是

Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.



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

Data cache unit (DCU) prefetcher — This prefetcher, also known as the streaming prefetcher, is triggered by an ascending access to very recently loaded data. The processor assumes that this access is part of a streaming algorithm and automatically fetches the next line.



所以我猜 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_miss远低于 offcore_requests.demand_rfo (即使 l2_rqsts.all_rfo 小于 offcore_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 的英特尔文档中我发现了以下内容:

Note: A prefetch promoted to Demand is counted from the promotion point.



所以我的猜测是 L2 预取被提升为 Demand 并计入 Demand 非核心请求。但它并没有解释 offcore_response.demand_rfo.any_response 之间的区别和 offcore_requests.demand_rfo现在几乎是两倍:
offcore_requests.demand_rfo 1 661 232 864
对比
offcore_response.demand_rfo.any_response 3 287 688 173
更新:
$ 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 .

更新:
$ 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

更新:
$ 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

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

假设: DCU RFO 预取缺少 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_response具有比 offcore_requests.demand_rfo 大得多的值

最佳答案

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

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

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

关于assembly - 为什么对非核心响应/非核心请求的需求过多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60390539/

相关文章:

c++ - 如何在 x86 和 x64 中对函数进行 thunk? (类似于 C++ 中的 std::bind,但是是动态的)

c - 数组转置及对应的汇编代码

c - 在不是地址/指针的值上使用LEA吗?

gcc - 如何编译一个简单的操作系统并使其可启动?

assembly - 组装中的 EBP、ESP 和堆栈框架

assembly - 具有只写目标并在英特尔的任何端口上运行的 x86 非 mov 指令?

c - 提高寄存器机虚拟机上循环的简单自制 JIT 的性能

汇编中的 Linux 64 命令行参数

linux - 将 16 位 DOS x86 程序集移植到 32 位 Linux x86 程序集

c - 指向视频内存 (0xB8000) 的指针有些奇怪