4、CPU性能监控:深入/proc/cpuinfo与/sys/devices/system/cpu,理解CPU调频策略
说到CPU性能监控,很多人第一反应就是跑个top或者htop看看占用率。嗯,这当然没错,但说实话,这只能看到表面。真正要摸透Jetson这颗ARM CPU的脾气,你得学会跟/proc/cpuinfo和/sys/devices/system/cpu这两个“内核窗口”打交道。
我个人习惯,拿到一块新的Jetson板子,第一件事不是跑分,而是先看看CPU到底能跑多快、当前在用什么策略跑。你想想看,如果连CPU的“档位”都没搞清楚,后面做性能调优就是瞎忙活。
4.1 从/proc/cpuinfo读懂CPU的“身份证”
/proc/cpuinfo这个文件,说白了就是CPU的户口本。里面记录了每个核心的型号、主频、特性等关键信息。我经常用它来快速确认当前系统是否识别了所有核心。
在Jetson上执行一下:
cat /proc/cpuinfo | grep -E "processor|model name|BogoMIPS|CPU part"
你会看到类似这样的输出:
processor : 0
model name : ARMv8 Processor rev 1 (v8l)
BogoMIPS : 62.50
CPU part : 0xd03
processor : 1
model name : ARMv8 Processor rev 1 (v8l)
BogoMIPS : 62.50
CPU part : 0xd03
processor : 2
model name : ARMv8 Processor rev 1 (v8l)
BogoMIPS : 62.50
CPU part : 0xd04
processor : 3
model name : ARMv8 Processor rev 1 (v8l)
BogoMIPS : 62.50
CPU part : 0xd04
这里有个细节要注意。CPU part字段的值,0xd03代表Cortex-A53核心(小核),0xd04代表Cortex-A73核心(大核)。我在项目中遇到过,有人发现Jetson Nano的CPU跑不满,查了半天才发现是大小核的调度策略没配好,导致所有任务都压在小核上了。
关键点:Jetson系列普遍采用ARM big.LITTLE架构。大核(高性能)和小核(低功耗)混在一起,/proc/cpuinfo能帮你一眼看出哪个核心是哪个类型。
4.2 /sys/devices/system/cpu:CPU的“控制面板”
如果说/proc/cpuinfo是只读的身份证,那/sys/devices/system/cpu就是你可以动手调节的控制面板。这里每个CPU核心都有一个独立的目录,比如cpu0、cpu1……里面藏着调频、调压、热管理的各种接口。
我最常用的几个文件:
- cpufreq/:调频相关的所有东西都在这里
- online:控制核心的开关(0表示离线,1表示在线)
- thermal_throttle/:温度降频的阈值设置
先看看当前CPU能跑哪些频率:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
输出可能是:
408000 720000 960000 1200000 1479000
嗯,单位是kHz。也就是说这颗核心最低408MHz,最高1.479GHz。我曾经调试一个实时视频处理项目,发现CPU频率一直在408MHz和720MHz之间跳变,导致画面卡顿。后来一查,是默认的调频策略太保守了。
4.3 CPU调频策略:性能与功耗的博弈
调频策略,英文叫governor。它决定了CPU在什么情况下升频、什么情况下降频。Jetson上常见的策略有这几种:
| 策略名称 | 行为特点 | 适用场景 |
|---|---|---|
| performance | 始终跑在最高频率 | 对延迟敏感、持续高负载的任务 |
| powersave | 始终跑在最低频率 | 后台低负载、省电优先 |
| ondemand | 按需快速升频,空闲时降频 | 日常使用,兼顾性能与功耗 |
| conservative | 缓慢升频,缓慢降频 | 负载波动不大的场景 |
| schedutil | 基于调度器负载反馈调频 | Linux内核4.7+推荐,更智能 |
查看当前策略很简单:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
Jetson默认通常是ondemand或schedutil。我个人建议,如果你在做推理任务或者实时控制,直接切到performance。别犹豫,省那点电不够你折腾的。
小技巧:想一次性设置所有核心的策略?用这个命令:
for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo performance > $i; done
注意,Jetson上有些核心可能没有独立的调频目录(比如某些小核被绑定在大核的调频域里),执行前先确认一下。
4.4 实战:手动锁定CPU频率
有时候光改策略还不够。比如你发现某个算法在1.2GHz时跑得最稳,再高就过热降频,再低又性能不够。这时候就需要手动锁定频率。
步骤很简单:
- 先把策略改成
userspace,这样内核才会听你的手动设置 - 然后写入目标频率
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo 1200000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
验证一下:
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
输出应该是1200000。嗯,锁住了。
注意:手动锁定频率后,CPU不会自动降频。如果你跑完高负载任务忘了改回去,板子会一直处于高功耗状态。我曾经有一次调试完忘记恢复,结果Jetson Nano在无负载时也发热严重,白白浪费了几个小时的电。所以养成好习惯:调试完记得改回ondemand或schedutil。
4.5 监控CPU频率的实时变化
光设置还不够,你得能看到它实时怎么变的。我写了个简单的一行命令,用来盯着频率跳变:
watch -n 1 "cat /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq"
这会每秒刷新一次,显示所有核心的当前频率。如果你看到频率在剧烈抖动,说明负载变化很大,或者调频策略太敏感了。
另外,/proc/cpuinfo里其实也有当前频率信息,但它是采样值,不如sysfs里的实时。我个人更推荐用sysfs接口。
4.6 避坑指南:Jetson特有的调频限制
最后说几个我在Jetson上踩过的坑:
- 热降频优先级高于调频策略:就算你设了
performance,一旦温度超过阈值(比如80°C),内核会强制降频。这时候你查scaling_cur_freq会发现频率上不去,别慌,先看看/sys/class/thermal/thermal_zone*/temp。 - 大小核的调频域可能不同:有些Jetson型号(比如Xavier NX),大核和小核属于不同的调频域,需要分别设置。别只改了cpu0就以为全搞定了。
- NVPower模式会覆盖你的设置:Jetson有NVIDIA自己的电源管理工具
nvpmodel,它会在后台修改调频策略。如果你发现手动设置不生效,先跑一下sudo nvpmodel -q看看当前模式。
好了,关于CPU性能监控和调频策略,核心就是这些。记住一句话:读懂/proc/cpuinfo是入门,玩转/sys/devices/system/cpu才是进阶。下一章我们聊聊GPU的监控,那个更刺激——毕竟Jetson的强项在GPU上。