gpt4 book ai didi

assembly - 如何使用 rdpmc 指令来计算 L1d 缓存未命中?

转载 作者:行者123 更新时间:2023-12-04 15:16:39 45 4
gpt4 key购买 nike

我想知道是否有任何单个事件可以捕获 L1D 缓存未命中。我试图通过在开始时使用 rdtsc 测量访问特定内存的延迟来捕获 L1d 缓存未命中。在我的设置中,如果发生 L1d 缓存未命中,它应该命中 L2 缓存。因此,我使用 RDTSC 测量访问内存的延迟,并将其与 L1 缓存延迟和 L2 缓存延迟进行比较。但是,由于噪音,我无法辨别它是击中了 L1 还是 L2。所以我决定使用 RDPMC。

我发现有几个 API 提供了一些功能来轻松监控 perf 事件,但我想直接在我的测试程序上使用 RDPMC 指令。我发现 MEM_INST_RETIRED.ALL_LOADS-MEM_LOAD_RETIRED.L1_HIT 可用于计算 L1D 中遗漏的退休加载指令的数量。(counting L1 cache misses with PAPI_read_counters gives unexpected results)。不过这个帖子好像是在说papi Api。

在执行 rdpmc 指令捕获特定事件之前,如何找到应该为 ecx 寄存器分配的值?另外,我想知道是否有任何单个事件可以告诉我 L1 未命中发生在两条 rdpmc 指令之间背靠背的一条内存加载指令,如下所示。

c = XXX; //I don't know what value should be assigned for what perf counter..
asm volatile(
"lfence"
"rdpmc"
"lfence"
"mov (0xdeadbeef), %%r10"//read memory
"mov %%eax, %%r10 //read lower 32 bits of counter
"lfence"
"rdpmc" //another rdpmc to capture difference
"sub %%r10, %%eax //sub two counter to get difference
:"=a"(a)
:"c"(c)
:"r10", "edx");

enter image description here

我目前使用的是 9900k coffee lake machine,所以我在 intel 手册中搜索了 coffee lake machine 的 perf counter number。似乎只在加载指令前后捕获两个 MEM_LOAD_RETIRED.L1_HIT 就足以捕获事件,但我不确定是否可以这样做。我也不太清楚如何将该 perf 事件编码为ecx寄存器。

最后,我想知道连续的 rdpmc 指令是否需要任何序列化指令。在我的例子中,因为我只放置了加载指令并测量是否发生了 L1d 缓存未命中,所以我将第一个 rdpmc 指令与 lfence 指令放在一起,并在最后一个 rdpmc 之前再放置一个 lfence 指令,以确保加载指令在第二个 rdpmc 之前完成。

添加代码

asm volatile (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
"lfence\n\t"
"rdpmc\n\t"
"lfence\n\t"
"mov %%eax, %%esi\n\t"
//measure
"mov (%4), %%r10\n\t"
"lfence\n\t"
"rdpmc\n\t"
"lfence\n\t"
"sub %%esi, %%eax\n\t"
"mov %%eax, (%0)\n\t"
:
:"r"(&perf[1]), "r"(&perf[2]), "r"(&perf[3]),
"r"(myAddr), "c"(0x0)
:"eax","edx","esi","r10", "memory");

我还用 isolcpu 固定了我的 3 号核心,并禁用了超线程以进行测试。 MSR寄存器已通过以下命令计算

    sudo wrmsr -p 3 0x186 0x4108D1 #L1 MISS

最佳答案

有一个 rdpmc 用法的例子:https://github.com/jdmccalpin/low-overhead-timers通过约翰 https://stackoverflow.com/a/60267195 (http://sites.utexas.edu/jdm4372/2018/07/23/comments-on-timing-short-code-sections-on-intel-processors/)。

还提到了准备使用工具来测量指令:https://arxiv.org/pdf/1911.03282.pdf https://github.com/andreas-abel/nanoBench

这个答案https://stackoverflow.com/a/60267531有使用 perf_event_open 设置事件计数器和 rdpmc 读取计数器的示例。

根据 https://www.felixcloutier.com/x86/rdpmc,rdpmc 未序列化,并且在两个未序列化的 rdpmc 之间也不是单调的:

The RDPMC instruction is not a serializing instruction; that is, it does not imply that all the events caused by the preceding instructions have been completed or that events caused by subsequent instructions have not begun. If an exact event count is desired, software must insert a serializing instruction (such as the CPUID instruction) before and/or after the RDPMC instruction.

Performing back-to-back fast reads are not guaranteed to be monotonic. To guarantee monotonicity on back-to-back reads, a serializing instruction must be placed between the two RDPMC instructions.

jevents 库可用于生成 PMC 事件选择器:https://github.com/andikleen/pmu-tools/tree/master/jevents .它被最新版本的 perf linux 分析工具内部使用。 jevents 也有简单的 api 来使用 rdpmc 命令

if (rdpmc_open(PERF_COUNT_HW_CPU_CYCLES, &ctx) < 0) ... error ...
start = rdpmc_read(&ctx);
... your workload ...
end = rdpmc_read(&ctx);

libpfm4 的 showevtinfo 可能会生成与 rdpmc 的 ecx 格式兼容的事件 ID,但我不确定:https://stackoverflow.com/a/46370111

使用 nanobench,我们可以检查 Skylake 事件的源代码: https://github.com/andreas-abel/nanoBench/blob/master/configs/cfg_Skylake_common.txt

D1.01 MEM_LOAD_RETIRED.L1_HIT
D1.08 MEM_LOAD_RETIRED.L1_MISS
D1.02 MEM_LOAD_RETIRED.L2_HIT
D1.10 MEM_LOAD_RETIRED.L2_MISS
D1.04 MEM_LOAD_RETIRED.L3_HIT
D1.20 MEM_LOAD_RETIRED.L3_MISS

解析于 https://github.com/andreas-abel/nanoBench/blob/master/common/nanoBench.c parse_counter_configs() 作为pfc_configs[n_pfc_configs].evt_numpfc_configs[n_pfc_configs].umask;在 configure_perf_ctrs_programmable 中编码为

        uint64_t perfevtselx = read_msr(MSR_IA32_PERFEVTSEL0+i);
perfevtselx &= ~(((uint64_t)1 << 32) - 1);

perfevtselx |= ((config.cmask & 0xFF) << 24);
perfevtselx |= (config.inv << 23);
perfevtselx |= (1ULL << 22);
perfevtselx |= (config.any << 21);
perfevtselx |= (config.edge << 18);
perfevtselx |= (os << 17);
perfevtselx |= (usr << 16);

perfevtselx |= ((config.umask & 0xFF) << 8);
perfevtselx |= (config.evt_num & 0xFF);

write_msr(MSR_IA32_PERFEVTSEL0+i, perfevtselx);

因此,写入 IA32_PERF_EVTSELx MSR 的寄存器值的两个低字节是 evt_num 和 umask。不确定它是如何转换成 rdpmc ecx 格式的。

John 说 rdpmc 命令需要“在 24-40 个周期范围内”并描述“英特尔架构使得无法以低延迟/开销从用户空间更改性能计数器事件选择编程。” https://community.intel.com/t5/Software-Tuning-Performance/Capturing-multiple-events-simultaneously-using-RDPMC-instruction/td-p/1097868

并且 rdpmc 的文档说了相同的 https://www.felixcloutier.com/x86/rdpmc :

The ECX register specifies the counter type (if the processor supports architectural performance monitoring) and counter index.General-purpose or special-purpose performance counters are specified with ECX[30] = 0

ECX 不包含要计数的确切事件,而是计数器的索引。有 2、4 或 8 个“可编程性能计数器”,您必须首先使用 wrmsr(在内核模式下)设置一些计数器,例如使用 MSR IA32_PERF_EVTSEL0 设置索引为 0 的计数器,然后使用 rdpmc 和 ecx[30] =0 且 ecx[29:0]=0;与 MSR IA32_PERF_EVTSEL3 一起使用 rdpmc 与 ecx[30]=0 和 ecx[29:0]=3。

我认为在测试代码之前和之后使用 PAPI API 设置计数器并从中获取读数会更容易。但 API 调用会增加开销,因此您的测试代码应设计为重复要测试的序列数次(数千次或更多次)。默认情况下,perfcounters 的 rdpmc/rdmsr 被 CR4 中的 PCE 标志禁用用于用户空间代码 - https://www.felixcloutier.com/x86/rdpmc (echo 2 >/sys/bus/event_source/devices/cpu/rdpmc);仅启用 linux 内核访问。用于设置计数器的 wrmsr 也被禁用。

有几种已知的方法可以在不使用性能计数器的情况下测量缓存层次结构延迟:https://www.7-cpu.com/utils.html和 lmbench/src/lat_mem_rd.c,但要获得实际的缓存延迟,需要进行一些手动后处理。

关于assembly - 如何使用 rdpmc 指令来计算 L1d 缓存未命中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64210648/

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