使用Linux读取ARMv8中的PMU计数器

使用Linux读取ARMv8中的PMU计数器,linux,caching,arm,counter,perf,Linux,Caching,Arm,Counter,Perf,我有一个树莓皮3与Linux。RPi3有一个四核cortex-A53,带有性能监控单元PMU v3。我执行cyclictest程序来做一些实时测试。CycleCTest是一个应用程序,您可以在其中设置周期和迭代次数,并计算延迟。因此,它执行一些执行,然后进入睡眠状态,直到nex周期,系统将其唤醒 我想读取每个CycleCTest执行中的缓存内存值,以查看它在执行时有多少缓存未命中。我不希望任务处于睡眠状态时出现未命中 我已尝试使用perf stat执行: perf stat -o result1

我有一个树莓皮3与Linux。RPi3有一个四核cortex-A53,带有性能监控单元PMU v3。我执行cyclictest程序来做一些实时测试。CycleCTest是一个应用程序,您可以在其中设置周期和迭代次数,并计算延迟。因此,它执行一些执行,然后进入睡眠状态,直到nex周期,系统将其唤醒

我想读取每个CycleCTest执行中的缓存内存值,以查看它在执行时有多少缓存未命中。我不希望任务处于睡眠状态时出现未命中

我已尝试使用perf stat执行:

perf stat -o result1.txt -r 10 -i -e armv8_pmuv3/l1d_cache/ 
    -e armv8_pmuv3/l1d_cache_refill/ 
    -e armv8_pmuv3/l1d_cache_wb/ 
    -e armv8_pmuv3/l1d_tlb_refill/ 
    -e armv8_pmuv3/l1i_cache/ 
    -e armv8_pmuv3/l1i_cache_refill/ 
    -e armv8_pmuv3/l1i_tlb_refill/ 
    -e armv8_pmuv3/l2d_cache/ 
    -e armv8_pmuv3/l2d_cache_refill/ 
    -e armv8_pmuv3/l2d_cache_wb/ 
    -e armv8_pmuv3/mem_access/ 
    cyclictest -l57600 -m -n -t1 -p80 -i50000 -h300 -q --histfile=666_data_50
但是,它确实提供了大约50%执行的信息:

Performance counter stats for 'cyclictest -l57600 -m -n -t1 -p80 -i50000 -h300 -q --histfile=666_data_50' (10 runs):

     937729229      armv8_pmuv3/l1d_cache/                                        ( +-  2.41% )  (54.50%)
      44736600      armv8_pmuv3/l1d_cache_refill/                                     ( +-  2.33% )  (54.39%)
      44784430      armv8_pmuv3/l1d_cache_wb/                                     ( +-  2.11% )  (54.33%)
        294033      armv8_pmuv3/l1d_tlb_refill/                                     ( +- 13.82% )  (54.21%)
    1924752301      armv8_pmuv3/l1i_cache/                                        ( +-  2.37% )  (54.41%)
     120581610      armv8_pmuv3/l1i_cache_refill/                                     ( +-  2.41% )  (54.46%)
        761651      armv8_pmuv3/l1i_tlb_refill/                                     ( +-  4.87% )  (54.70%)
     215103404      armv8_pmuv3/l2d_cache/                                        ( +-  2.28% )  (54.69%)
      30884575      armv8_pmuv3/l2d_cache_refill/                                     ( +-  1.44% )  (54.83%)
      11424917      armv8_pmuv3/l2d_cache_wb/                                     ( +-  2.03% )  (54.76%)
     943041718      armv8_pmuv3/mem_access/                                       ( +-  2.41% )  (54.74%)

2904.940283006 seconds time elapsed                                          ( +-  0.07% )
我不知道这个计数器是在运行时只统计这个任务的缓存信息,还是在睡眠时也统计。有人知道吗?我还有其他的应用程序在运行,它们是否可以像我在perf stat中指定的那样修改这些计数器的值

如果无法读取仅任务在运行时的计数器的准确值?使用模块还是自定义用户空间应用程序


谢谢

每个性能监视器硬件都受到通道数量的限制:每时每刻可以同时统计多少个事件。例如,许多现代x86/x86_64可能为每个cpu核心提供4个灵活通道和3个固定通道。当您向探查器请求更多事件时,它将像和一样进行多路复用。当多路复用处于活动状态时,在55%的运行时间内测量到一些事件e1,并且perf stat(性能统计)而不是?C.多路复用。这种推断可能有一些错误

带有PMU v3的cortex-A53只有六个通道: PMEVCNTR0_EL0-PMEVCNTR5_EL0和PMEVTYPER0_EL0-PMEVTYPER5_EL0。在一次运行测试时,尝试在不超过6个事件的情况下启动perf stat,以关闭事件多路复用:

perf stat -o result1.txt -r 10 -i \
    -e armv8_pmuv3/l1d_cache/  \
    -e armv8_pmuv3/l1d_cache_refill/  \
    -e armv8_pmuv3/l1d_cache_wb/  \
    -e armv8_pmuv3/l1d_tlb_refill/  \
    -e armv8_pmuv3/l1i_cache/  \
    -e armv8_pmuv3/l1i_cache_refill/  \
    cyclictest -l57600 -m -n -t1 -p80 -i50000 -h300 -q --histfile=666_data_50

perf stat -o result2.txt -r 10 -i \
    -e armv8_pmuv3/l1i_tlb_refill/  \
    -e armv8_pmuv3/l2d_cache/  \
    -e armv8_pmuv3/l2d_cache_refill/  \
    -e armv8_pmuv3/l2d_cache_wb/  \
    -e armv8_pmuv3/mem_access/  \
    cyclictest -l57600 -m -n -t1 -p80 -i50000 -h300 -q --histfile=666_data_50

您也可以尝试将事件分组到集合中:-e\{event1,event2…,event6\}和set将与其他集合多路复用。

我认为PMU计数器是异常级别1 EL1或更高,因此您需要root权限来执行此操作。似乎从任何控件(如register)引导ARM中任何有趣的内容都需要EL1或更高版本。您甚至无法读取计算机的基本功能,例如计算机是否有可选的CRC和加密指令。@jww:Linux perf已在内核模式下执行所有perf计数器访问。它虚拟化了硬件计数器,因此当您像那样使用perf stat时,它们是每个进程的,而没有-a或其他一些系统范围的选项,这些选项将在其他任务运行时保持计数器计数。使用这种方式的perf stat只是计算进程,而不是当前CPU或其他内核正在做的任何事情。@PeterCordes因此,如果我理解正确,我做得很好。但是,如果我执行两次,得到的值就完全不同了。此外,如果在一次测试中我将周期设置为50ms,在另一次测试中设置为100us,则l1d_缓存、l1i_缓存和l2d_缓存的数量在第二次测试中会更低。作为同一个应用程序,它不应该有类似的值?我认为您做得对,除非ARM上的性能与x86非常不同。如果每单位时间的访问次数相似,那么让测试运行50毫秒应该会产生比仅100个美国多得多的L1D访问。这是访问次数,而不是命中率。你没有说这个程序计算的是什么。内存访问?或者别的什么?如果缓存在测试周期之间被其他工作污染,或者在唤醒后被安排在不同的内核上,那么更短的周期将意味着更多的未命中/更低的吞吐量/同时更少的总访问。你的系统空闲吗?您是否查看了cpu迁移性能事件?您是否尝试使用taskset-C0性能统计。。。要将微基准锁定到核心0?