gpt4 book ai didi

c - L2 HW预取器真的有用吗?

转载 作者:行者123 更新时间:2023-12-03 15:46:23 27 4
gpt4 key购买 nike

我在威士忌湖i7-8565U 上,分析性能计数器和复制512 KiB数据的时间(是L2高速缓存大小的两倍),并且对L2硬件预取器的工作遇到了一些误解。

Intel Manual Vol.4 MSR中,有MSR 0x1A4的位0用于控制L2硬件预取器(禁用1)。

考虑以下基准:
memcopy.h:

void *avx_memcpy_forward_lsls(void *restrict, const void *restrict, size_t);
memcopy.S:
avx_memcpy_forward_lsls:
shr rdx, 0x3
xor rcx, rcx
avx_memcpy_forward_loop_lsls:
vmovdqa ymm0, [rsi + 8*rcx]
vmovdqa [rdi + rcx*8], ymm0
vmovdqa ymm1, [rsi + 8*rcx + 0x20]
vmovdqa [rdi + rcx*8 + 0x20], ymm1
add rcx, 0x08
cmp rdx, rcx
ja avx_memcpy_forward_loop_lsls
ret
main.c:
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <x86intrin.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include "memcopy.h"

#define ITERATIONS 1000
#define BUF_SIZE 512 * 1024

_Alignas(64) char src[BUF_SIZE];
_Alignas(64) char dest[BUF_SIZE];

static void __run_benchmark(unsigned runs, unsigned run_iterations,
void *(*fn)(void *, const void*, size_t), void *dest, const void* src, size_t sz);

#define run_benchmark(runs, run_iterations, fn, dest, src, sz) \
do{\
printf("Benchmarking " #fn "\n");\
__run_benchmark(runs, run_iterations, fn, dest, src, sz);\
}while(0)

int main(void){
int fd = open("/dev/urandom", O_RDONLY);
read(fd, src, sizeof src);
run_benchmark(20, ITERATIONS, avx_memcpy_forward_lsls, dest, src, BUF_SIZE);
}

static inline void benchmark_copy_function(unsigned iterations, void *(*fn)(void *, const void *, size_t),
void *restrict dest, const void *restrict src, size_t sz){
while(iterations --> 0){
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
fn(dest, src, sz);
}
}

static void __run_benchmark(unsigned runs, unsigned run_iterations,
void *(*fn)(void *, const void*, size_t), void *dest, const void* src, size_t sz){
unsigned current_run = 1;
while(current_run <= runs){
benchmark_copy_function(run_iterations, fn, dest, src, sz);
printf("Run %d finished\n", current_run);
current_run++;
}
}

考虑编译的 main.c的2次运行


MSR:
$ sudo rdmsr -p 0 0x1A4
0
Run:
$ taskset -c 0 sudo ../profile.sh ./bin 

Performance counter stats for './bin':

10 486 164 071 L1-dcache-loads (12,13%)
10 461 354 384 L1-dcache-load-misses # 99,76% of all L1-dcache hits (12,05%)
10 481 930 413 L1-dcache-stores (12,05%)
10 461 136 686 l1d.replacement (12,12%)
31 466 394 422 l1d_pend_miss.fb_full (12,11%)
211 853 643 294 l1d_pend_miss.pending (12,09%)
1 759 204 317 LLC-loads (12,16%)
31 007 LLC-load-misses # 0,00% of all LL-cache hits (12,16%)
3 154 901 630 LLC-stores (6,19%)
15 867 315 545 l2_rqsts.all_pf (9,22%)
0 sw_prefetch_access.t1_t2 (12,22%)
1 393 306 l2_lines_out.useless_hwpf (12,16%)
3 549 170 919 l2_rqsts.pf_hit (12,09%)
12 356 247 643 l2_rqsts.pf_miss (12,06%)
0 load_hit_pre.sw_pf (12,09%)
3 159 712 695 l2_rqsts.rfo_hit (12,06%)
1 207 642 335 l2_rqsts.rfo_miss (12,02%)
4 366 526 618 l2_rqsts.all_rfo (12,06%)
5 240 013 774 offcore_requests.all_data_rd (12,06%)
19 936 657 118 offcore_requests.all_requests (12,09%)
1 761 660 763 offcore_response.demand_data_rd.any_response (12,12%)
287 044 397 bus-cycles (12,15%)
36 816 767 779 resource_stalls.any (12,15%)
36 553 997 653 resource_stalls.sb (12,15%)
38 035 066 210 uops_retired.stall_cycles (12,12%)
24 766 225 119 uops_executed.stall_cycles (12,09%)
40 478 455 041 uops_issued.stall_cycles (12,05%)
24 497 256 548 cycle_activity.stalls_l1d_miss (12,02%)
12 611 038 018 cycle_activity.stalls_l2_miss (12,09%)
10 228 869 cycle_activity.stalls_l3_miss (12,12%)
24 707 614 483 cycle_activity.stalls_mem_any (12,22%)
24 776 110 104 cycle_activity.stalls_total (12,22%)
48 914 478 241 cycles (12,19%)

12,155774555 seconds time elapsed

11,984577000 seconds user
0,015984000 seconds sys

II。
MSR:
$ sudo rdmsr -p 0 0x1A4
1
Run:
$ taskset -c 0 sudo ../profile.sh ./bin

Performance counter stats for './bin':

10 508 027 832 L1-dcache-loads (12,05%)
10 463 643 206 L1-dcache-load-misses # 99,58% of all L1-dcache hits (12,09%)
10 481 296 605 L1-dcache-stores (12,12%)
10 444 854 468 l1d.replacement (12,15%)
29 287 445 744 l1d_pend_miss.fb_full (12,17%)
205 569 630 707 l1d_pend_miss.pending (12,17%)
5 103 444 329 LLC-loads (12,17%)
33 406 LLC-load-misses # 0,00% of all LL-cache hits (12,17%)
9 567 917 742 LLC-stores (6,08%)
1 157 237 980 l2_rqsts.all_pf (9,12%)
0 sw_prefetch_access.t1_t2 (12,17%)
301 471 l2_lines_out.useless_hwpf (12,17%)
218 528 985 l2_rqsts.pf_hit (12,17%)
938 735 722 l2_rqsts.pf_miss (12,17%)
0 load_hit_pre.sw_pf (12,17%)
4 096 281 l2_rqsts.rfo_hit (12,17%)
4 972 640 931 l2_rqsts.rfo_miss (12,17%)
4 976 006 805 l2_rqsts.all_rfo (12,17%)
5 175 544 191 offcore_requests.all_data_rd (12,17%)
15 772 124 082 offcore_requests.all_requests (12,17%)
5 120 635 892 offcore_response.demand_data_rd.any_response (12,17%)
292 980 395 bus-cycles (12,17%)
37 592 020 151 resource_stalls.any (12,14%)
37 317 091 982 resource_stalls.sb (12,11%)
38 121 826 730 uops_retired.stall_cycles (12,08%)
25 430 699 605 uops_executed.stall_cycles (12,04%)
41 416 190 037 uops_issued.stall_cycles (12,04%)
25 326 579 070 cycle_activity.stalls_l1d_miss (12,04%)
25 019 148 253 cycle_activity.stalls_l2_miss (12,03%)
7 384 770 cycle_activity.stalls_l3_miss (12,03%)
25 442 709 033 cycle_activity.stalls_mem_any (12,03%)
25 406 897 956 cycle_activity.stalls_total (12,03%)
49 877 044 086 cycles (12,03%)

12,231406658 seconds time elapsed

12,226386000 seconds user
0,004000000 seconds sys

我注意到柜台:
12 611 038 018 cycle_activity.stalls_l2_miss v/s 25 019 148 253 cycle_activity.stalls_l2_miss
提示正在应用禁用M2硬件预取器的MSR。其他与L2/LLC相关的内容也存在显着差异。 差异在不同的运行之间是可重现的。问题在于 total time和周期几乎没有区别:
48 914 478 241 cycles v/s 49 877 044 086 cycles 12,155774555 seconds time elapsed v/s 12,231406658 seconds time elapsed
问题: L2遗漏是否被其他性能限制因素隐藏?如果是,您能建议看一下哪些计数器来理解它吗?

最佳答案

是的,L2拖缆在很多时候确实很有帮助。

memcpy没有任何隐藏的计算延迟,因此我想它可以让OoO exec资源(ROB大小)处理您从更多L2未命中获得的额外负载延迟,至少在这种情况下,您会从中获得所有L3命中使用适合L3的中型工作集(1MiB),不需要进行预取就可以使L3命中。

唯一的指令是加载/存储(和循环开销),因此OoO窗口包含了相当遥远的需求负载。

如果L2空间预取器和L1d预取器在此方面有所帮助,则为IDK。

预测以检验该假设:增大阵列大小,以便您错过L3,一旦OoO exec不足以掩盖一路直入DRAM的负载延迟,您可能会发现总体时间有所不同。硬件预取触发更远的距离可以有所帮助。

硬件预取的另一个大好处是,它可以跟上您的计算速度,因此您获得了L2命中率。 (在具有中等长度计算但没有循环携带的依赖链的循环中。)

当ROB容量没有其他压力时,需求负载和OoO exec可以利用可用(单线程)内存带宽做很多事情。

还应注意,在Intel CPU上,每个高速缓存未命中可能会花费一定量的相关uops 后端回放(来自RS/调度程序),当预期数据到达时,L1d和L2未命中一个。在那之后,显然核心在等待数据从L3到达时乐观地发送垃圾邮件。

(请参阅https://chat.stackoverflow.com/rooms/206639/discussion-on-question-by-beeonrope-are-load-ops-deallocated-from-the-rs-when-thAre load ops deallocated from the RS when they dispatch, complete or some other time?)

不是缓存未命中本身。在这种情况下,将是商店的说明。更具体地说,端口4的存储数据uop。使用32字节的存储区以及L3带宽上的瓶颈意味着每个时钟我们不接近1个端口4个uop。

关于c - L2 HW预取器真的有用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60027056/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com