为什么有太多需求 rfo offcore 响应/offcore 请求?
Why are there too many demand rfo offcore responses /offcore requests?
Whiskey Lake i7-8565U
/Ubuntu 18.04
/HT enabled
考虑以下代码,将一些恰好在寄存器 ymm0
和 ymm1
中的垃圾数据写入 16 MiB 静态分配的 WB 内存中由 6400 次迭代组成的循环(因此页面错误的影响可以忽略不计):
;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 遵循 "access type":如果是 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 预取被提升为需求并计入需求外核请求。但它并没有解释 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
。
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 预取缺少 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
有更大的价值
在我看来,循环正在写入 2^18 个缓存行,并且有一个外部循环(问题中未显示)执行内部循环(显示的循环)6400 次。因此,需求 RFO 的预期总数为 2^18*6400 = 1,677,721,600,退休存储指令的预期数量为 1677721600*2 = 3,355,443,200。实测门店数量L1-dcache-stores
约为34.1亿,比预期多出约5500万。这个事件计数应该是准确的,所以我假设还有其他代码没有显示在影响事件计数的问题中。负载事件计数还表明有很多负载来自某处,这对事件计数有重大影响 l2_rqsts.all_pf
、l2_rqsts.pf_hit
、l2_rqsts.pf_miss
。我已经在我的评论中询问过测量中是否包含任何其他重要代码。
从启用所有预取器的第一个实验的结果来看,l2_rqsts.rfo_hit
+ offcore_requests.demand_rfo
加起来的数量几乎等于需求 RFO 的预期数量。 L2 streamer 实际上可以预取 RFO,如 Intel 优化手册中所述,该手册解释了如何可以 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
是可靠的。
对于问题 1,答案(至少在 Skylake 上是这样,但很可能与 Whiskey lake 相同)是 L2 RFO 事件在它们发生时不计算在内由预取启动:不是在预取被触发时,甚至是当 RFO 后来在 L2 中命中或未命中时。您可以通过设置事件的预取位(在 umask 中设置 0x10)来计算这些事件,在这种情况下,您会看到双重计数,如 .
您看到的事件是 RFO 的随机子集,其中 L2 预取器没有帮助。 offcore 计数器显然没有这样的问题:即使请求是由预取发起的,当需求命中正在进行的请求时,它也可以提升为需求请求。
您可以找到更多详细信息 here,并且您应该仔细检查您的 perf 版本使用了哪些事件,因为英特尔更改了最后一个 link 中描述的事件定义。
Whiskey Lake i7-8565U
/Ubuntu 18.04
/HT enabled
考虑以下代码,将一些恰好在寄存器 ymm0
和 ymm1
中的垃圾数据写入 16 MiB 静态分配的 WB 内存中由 6400 次迭代组成的循环(因此页面错误的影响可以忽略不计):
;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
:
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 遵循 "access type":如果是 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 预取被提升为需求并计入需求外核请求。但它并没有解释 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
。
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 预取缺少 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
在我看来,循环正在写入 2^18 个缓存行,并且有一个外部循环(问题中未显示)执行内部循环(显示的循环)6400 次。因此,需求 RFO 的预期总数为 2^18*6400 = 1,677,721,600,退休存储指令的预期数量为 1677721600*2 = 3,355,443,200。实测门店数量L1-dcache-stores
约为34.1亿,比预期多出约5500万。这个事件计数应该是准确的,所以我假设还有其他代码没有显示在影响事件计数的问题中。负载事件计数还表明有很多负载来自某处,这对事件计数有重大影响 l2_rqsts.all_pf
、l2_rqsts.pf_hit
、l2_rqsts.pf_miss
。我已经在我的评论中询问过测量中是否包含任何其他重要代码。
从启用所有预取器的第一个实验的结果来看,l2_rqsts.rfo_hit
+ offcore_requests.demand_rfo
加起来的数量几乎等于需求 RFO 的预期数量。 L2 streamer 实际上可以预取 RFO,如 Intel 优化手册中所述,该手册解释了如何可以 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
是可靠的。
对于问题 1,答案(至少在 Skylake 上是这样,但很可能与 Whiskey lake 相同)是 L2 RFO 事件在它们发生时不计算在内由预取启动:不是在预取被触发时,甚至是当 RFO 后来在 L2 中命中或未命中时。您可以通过设置事件的预取位(在 umask 中设置 0x10)来计算这些事件,在这种情况下,您会看到双重计数,如
您看到的事件是 RFO 的随机子集,其中 L2 预取器没有帮助。 offcore 计数器显然没有这样的问题:即使请求是由预取发起的,当需求命中正在进行的请求时,它也可以提升为需求请求。
您可以找到更多详细信息 here,并且您应该仔细检查您的 perf 版本使用了哪些事件,因为英特尔更改了最后一个 link 中描述的事件定义。