【发布时间】:2020-06-08 22:42:37
【问题描述】:
Whiskey Lake i7-8565U/Ubuntu 18.04/HT enabled
考虑以下代码,该代码将恰好位于寄存器 ymm0 和 ymm1 中的一些垃圾数据写入 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_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 的英特尔文档中,我发现了以下内容:
注意:提升为 Demand 的预取将从提升中计算 点。
所以我的猜测是 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
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
即使预取器被禁用 perf 将 12 报告为 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_response 比offcore_requests.demand_rfo 具有更大的价值
【问题讨论】:
-
应该有多少个需求 RFO?我无法从显示的代码中分辨出来,因为我不知道
rdx中的内容以及正在访问多少不同的物理页面。你预计有多少人会在 L1 中错过?你只计算用户模式事件吗?正在使用perf?如果是,那么这些计数是否包括任何其他重要的代码片段。 HT被禁用了吗?您可以删除offcore_requests_outstanding.demand_rfo和l2_rqsts.all_demand_data_rd以避免在禁用 HT 的情况下进行多路复用。多次重复实验并显示每个事件的标准偏差。
标签: assembly x86 x86-64 cpu-cache rfo