如何使用 Rocket Lake 通过 perf 访问 RAPL?

问题描述

我有一个 Rocket Lake cpu(11900K),但是 perf 还不支持它的访问电源事件,我该怎么做?

性能事件列表:

pastebin.com + tcsSdxUx

我的操作系统:Ubuntu 20.10 内核 5.12-RC6 性能版本:5.12-RC6

我可以使用 rapl-read.c 读取 Rapl 值(链接http://web.eece.maine.edu/~vweaver/projects/rapl/

但是 rapl-read.c 不能用来分析正在运行的程序。我希望对正在运行的程序做性能分析,不仅是电源事件,还有周期、分支等,Intel 的 SoCwatch 做不了这么多。

有什么方法可以为 perf 添加 Rocket Lake 电源事件支持吗?我不知道原始电源事件计数器。

更新 #1:

uname -a 输出

Linux u128 5.12.0-051200rc6-generic #202104042231 SMP Sun Apr 4 22:33:57 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

更新#2: rapl-read -m 输出

RAPL read -- use -s for sysfs,-p for perf_event,-m for msr

找到 RocketLake 处理器类型 0 (0),1 (0),2 (0),3 (0),4 (0),5 (0),6 (0),7 (0)

    Detected 8 cores in 1 packages

尝试 /dev/msr 接口收集结果

    Listing paramaters for package #0
            Power units = 0.125W
            cpu Energy units = 0.00006104J
            DRAM Energy units = 0.00006104J
            Time units = 0.00097656s

            Package thermal spec: 125.000W
            Package minimum power: 0.000W
            Package maximum power: 0.000W
            Package maximum time window: 0.000000s
            Package power limits are unlocked
            Package power limit #1: 4095.875W for 0.108398s (enabled,not_clamped)
            Package power limit #2: 4095.875W for 0.032227s (disabled,not_clamped)
    PowerPlane1 (on-core GPU if avail) 0 policy: 16


    Sleeping 1 second

    Package 0:
            Package energy: 62.846985J
            PowerPlane0 (cores): 45.371277J
            PowerPlane1 (on-core GPU if avail): 0.000000 J
            DRAM: 0.000000J
            PSYS: -0.000000J

注意:能量测量可能会在 60 秒左右溢出 因此,请尝试更频繁地对计数器进行采样。

更新 #3: 我发现很难简单地使用 rapl msr 来获得整个功耗:

ujtoj=1000000;
bgn_energy=$(rdmsr -d 0x611);
time sh doit.sh;
end_energy=$(rdmsr -d 0x611);
printf '%.3f\n' "$(((end_energy - bgn_energy)/ujtoj))e-3"

输出

real    2m58.411s
user    2m58.068s
sys     0m0.168s
0.197

doit.sh 是运行 SPEC cpu2017 500.perlbench 测试的 shell 脚本。对于 Zen 3,perf stat 输出的能耗(power/energy_pkg)约为 7486.61J,远高于简单使用 rdmsr 输出的“0.197”。

更新#4: 现在我找到了另一种方法解决我的问题。 通过添加一些“#define”和“case:”代码可以很容易地添加 RKL 支持

--------------------------------------------------------------------------------
cpu name:   11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz
cpu type:   Intel Rocketlake processor
cpu clock:  3.50 GHz
--------------------------------------------------------------------------------
Group 1: ENERGY
+-----------------------+---------+--------------+
|         Event         | Counter |  HWThread 6  |
+-----------------------+---------+--------------+
|   INSTR_RETIRED_ANY   |  FIXC0  | 996795747147 |
| cpu_CLK_UNHALTED_CORE |  FIXC1  | 321084408076 |
|  cpu_CLK_UNHALTED_REF |  FIXC2  | 216809163858 |
|       TEMP_CORE       |   TMP0  |           65 |
|     PWR_PKG_ENERGY    |   PWR0  |    4050.2952 |
|     PWR_PP0_ENERGY    |   PWR1  |    2982.4675 |
|    PWR_DRAM_ENERGY    |   PWR3  |            0 |
+-----------------------+---------+--------------+
+----------------------+------------+
|        Metric        | HWThread 6 |
+----------------------+------------+
|  Runtime (RDTSC) [s] |    62.0025 |
| Runtime unhalted [s] |    91.6329 |
|      Clock [MHz]     |  5189.3093 |
|          CPI         |     0.3221 |
|    Temperature [C]   |         65 |
|      Energy [J]      |  4050.2952 |
|       Power [W]      |    65.3247 |
|    Energy PP0 [J]    |  2982.4675 |
|     Power PP0 [W]    |    48.1024 |
|    Energy DRAM [J]   |          0 |
|    Power DRAM [W]    |          0 |
+----------------------+------------+

解决方法

在 v5.9-rc5 中添加了 intel_rapl 驱动程序中对 RKL 的支持,在 v5.11-rc1 中添加了 core 和 uncore perf 事件。你确定你有 v5.12-rc6 吗? uname -a 打印什么? Ubuntu 20.10 基于 v5.8 和其他向后移植的补丁(其中一个补丁支持现代英特尔客户端处理器上可用的所有 uncore_imc 事件)。

如果 perf_event 子系统在不受支持的处理器模型上运行,您可以仅使用架构事件。但是您仍然可以使用 perf 手册页中记录的原始事件编码。这种方法只对没有约束的事件可靠,因为 perf_event 不知道不受支持的模型上可能存在的任何约束。大多数事件没有限制,所以这不是一个大问题。

我不知道您为什么认为 rapl-read 不能用于分析程序。没有特定于程序或特定于核心的 RAPL 域。您可以使用 rapl-read 选项运行 -m 以直接访问 MSR 以获取能量读数,然后是您的程序,然后再次运行 rapl-read。两个读数之间的差异为您提供了每个支持域的能耗。请注意,您必须修改 rapl_msr() 函数,以便它在两次读数之间调用您的程序,而不仅仅是执行 sleep(1)。否则,它只会在大约一秒钟内报告能源消耗,而与您的程序的能源消耗几乎没有任何相关性。

rapl-read 当前不支持 RKL(或任何最新的 Intel 处理器)。但是您可以通过首先从 cat /proc/cpuinfo 确定 CPU 模型,然后添加类似于当前支持的模型的宏定义(如 #define CPU_ROCKETLAKE model)来轻松添加 RAPL 支持。我在 CPU 模式下只看到两个 switch 语句,一个在 detect_cpu(void) 中,一个在 rapl_msr(int core,int cpu_model) 中。只需为 CPU_ROCKETLAKE 添加一个案例。 RKL 与 SKL 具有相同的 RAPL 域,因此在两个函数中都与 CPU_SKYLAKE 放在一起。那应该这样做。或者,您可以完全避免使用 rapl-read,而只需在读取读数、运行程序然后再次读取读数的 shell 脚本中使用 wrmsrrdmsr

MSR 0x611 是 MSR_PKG_ENERGY_STATUS,它报告一个 32 位无符号值。这个值的单位是MSR_RAPL_POWER_UNIT,默认是15.26uj。你似乎认为它是微焦耳。您确定这就是MSR_RAPL_POWER_UNIT 所说的吗?即便如此,表达式 $(((end_energy - bgn_energy)/ujtoj))e-3 的结果仍以千焦为单位,那么您如何将它与 Zen3 上的 power/energy_pkg 进行比较,后者显然以焦耳为单位?

如果正确的单位是 15.26uj,那么在英特尔处理器上的测量结果将是 15.26*197000000 = 3,009,226,220,000 焦耳(大约 3000 吉焦耳)。但由于只有 MSR 寄存器的最低 32 位有效,因此最大值为 15.26*(2^32 - 1) = 65,541,200,921.7 焦耳(约 65 吉焦耳)。所以我认为单位不是15.26uj。

使用 500.perlbench 输入的 test 基准测试似乎需要大约 3 分钟才能完成。很难知道 MSR_PKG_ENERGY_STATUS 是否回绕,因为报告的数字不是负数。

我认为最好在一个内核上运行 500.perlbench,然后在另一个内核上运行每隔几秒读取一次 MSR_PKG_ENERGY_STATUS 的脚本。例如,您可以将 rdmsr -d 0x611 放入循环中,并在每次迭代中休眠若干秒。由于 500.perlbench 需要相对较长的时间才能完成,因此您不必完全同时启动这两个程序。通过这种方式,您可以模仿 perf stat -a -I 1000 -e power/energy-pkg/ 的工作方式,如果英特尔平台上的内核支持事件 power/energy-pkg/

我已在 perf power consumption measure: How does it work? 讨论了英特尔基于 RAPL 的能源测量的可靠性。不过不知道有没有人验证过AMD的RAPL的准确性。我不清楚英特尔的 MSR_PKG_ENERGY_STATUS 和 AMD 的 Core::X86::Msr::PKG_ENERGY_STAT 之间的比较在多大程度上有意义。