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
报告 12
如 pf_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/