3、CPU调频策略:深入解析Linux cpufreq框架
各位同学,咱们今天聊聊CPU调频。说白了,就是让CPU在「省电」和「跑得快」之间找个平衡点。我在嵌入式项目里摸爬滚打这么多年,发现很多性能问题,根源其实都在调频策略上。
Linux内核里有个叫cpufreq的框架,专门干这事。它提供了几种governor(调频策略),各有各的脾气。咱们一个个来看。
3.1 cpufreq框架概览
先说说cpufreq是啥。它是个内核子系统,负责动态调整CPU频率。你想想看,手机刷网页时CPU全速跑,那不是浪费电吗?cpufreq就是干这个的——根据负载动态调频。
它的核心组件包括:
- cpufreq driver:硬件相关的驱动,负责实际读写频率寄存器
- cpufreq governor:策略模块,决定「什么时候该升频、什么时候该降频」
- cpufreq core:中间层,协调driver和governor
嗯,这里要注意:不同的SoC(比如瑞芯微的RK3588、RK3568)用的driver可能不一样,但governor是通用的。所以咱们重点讲governor。
3.2 五种governor深度解析
3.2.1 performance:简单粗暴,全速运行
这个最简单。CPU永远跑在最高频率,不降频。适合对延迟要求极高的场景,比如实时音频处理、游戏渲染。
适用场景:跑分、低延迟任务、调试阶段
缺点:功耗爆炸,发热严重
我个人习惯在调试阶段用performance,排除调频带来的干扰。但量产产品里,除非你不在乎续航和散热,否则别用。
3.2.2 powersave:省电至上,低频运行
和performance相反,CPU永远跑在最低频率。适合后台任务、待机场景。
注意:别在交互式应用里用powersave。我曾经在一个平板项目里试过,用户点一下屏幕要等半秒才有反应——那体验,简直灾难。
3.2.3 ondemand:按需调频,经典策略
这是Linux里最经典的governor。它监控CPU使用率,当负载超过某个阈值(默认95%)时,立刻跳到最高频率;负载降下来后,再逐步降频。
它的工作原理:
- 每隔一段时间(采样周期,默认10ms)检查CPU负载
- 如果负载 > up_threshold(默认95%),直接跳到最高频
- 如果负载 < down_threshold(默认60%),逐步降频
说白了,ondemand是个「反应快、但有点毛躁」的策略。它升频很激进,降频却很保守。我在项目中遇到过一个问题:某个视频解码任务,负载在80%-100%之间波动,导致CPU频繁在高低频之间切换,反而增加了功耗。
调优技巧:可以调整up_threshold和sampling_rate。比如把阈值降到80%,让CPU更早升频;或者把采样周期拉长到20ms,减少切换频率。
3.2.4 conservative:保守派,平滑调频
conservative和ondemand很像,但更「温柔」。它不会一下子跳到最高频,而是逐步升频,每次只升一档。
它的特点:
- 升频慢,降频也慢
- 频率变化平滑,功耗波动小
- 适合负载变化不剧烈的场景
你想想看,如果ondemand是个急性子,那conservative就是个慢性子。我建议在电池供电的设备上用conservative,比如智能手表、IoT传感器。但要注意,如果负载突然飙升(比如用户突然滑动屏幕),conservative可能反应不过来。
3.2.5 schedutil:调度器驱动的调频
这是目前最先进的governor。它不依赖采样周期,而是直接从调度器获取每个任务的负载信息。说白了,调度器知道每个任务需要多少算力,schedutil就根据这个信息来调频。
它的优势:
- 响应更快:调度器在分配任务时就知道负载,不需要等采样周期
- 更精准:能区分「前台任务」和「后台任务」,优先保证交互流畅
- 功耗更低:避免ondemand那种「过度调频」的问题
适用场景:Android设备、交互式应用、多任务场景
注意:需要内核支持SCHED_DEADLINE或CFS调度器,且cpufreq driver要支持setpolicy接口
我记得在RK3588的开发板上测试过,schedutil比ondemand的功耗低了约15%,但响应速度反而更快。嗯,这就是调度器驱动的魅力。
3.3 五种governor对比
| Governor | 调频策略 | 响应速度 | 功耗 | 适用场景 |
|---|---|---|---|---|
| performance | 固定最高频 | 最快 | 最高 | 跑分、低延迟任务 |
| powersave | 固定最低频 | 最慢 | 最低 | 待机、后台任务 |
| ondemand | 按阈值跳频 | 快 | 中等 | 通用场景 |
| conservative | 逐步调频 | 慢 | 较低 | 电池供电设备 |
| schedutil | 调度器驱动 | 最快 | 最低 | 交互式、多任务 |
3.4 实战:如何切换governor
在瑞芯微平台上,切换governor很简单。直接写sysfs节点就行:
# 查看当前governor
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# 切换到schedutil
echo schedutil > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# 查看可用governor
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
避坑指南:我曾经在RK3568上遇到过一个问题——切换governor后,CPU频率卡在某个值不动了。后来发现是内核没编译对应的governor模块。记得检查内核配置:CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y。
3.5 我的建议
说了这么多,到底该用哪个?我个人的经验是:
- 交互式设备(平板、手机):首选schedutil,次选ondemand
- 电池供电的IoT设备:用conservative,或者自己调优ondemand的参数
- 服务器/工控机:performance或者ondemand,看你对功耗的容忍度
- 调试阶段:用performance,排除调频干扰
最后说一句:没有最好的governor,只有最适合你场景的governor。调频策略的优化,说白了就是在「性能」和「功耗」之间做取舍。你想想看,是不是这个理?