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_thresholdsampling_rate。比如把阈值降到80%,让CPU更早升频;或者把采样周期拉长到20ms,减少切换频率。

3.2.4 conservative:保守派,平滑调频

conservative和ondemand很像,但更「温柔」。它不会一下子跳到最高频,而是逐步升频,每次只升一档。

它的特点:

  • 升频慢,降频也慢
  • 频率变化平滑,功耗波动小
  • 适合负载变化不剧烈的场景

你想想看,如果ondemand是个急性子,那conservative就是个慢性子。我建议在电池供电的设备上用conservative,比如智能手表、IoT传感器。但要注意,如果负载突然飙升(比如用户突然滑动屏幕),conservative可能反应不过来。

3.2.5 schedutil:调度器驱动的调频

这是目前最先进的governor。它不依赖采样周期,而是直接从调度器获取每个任务的负载信息。说白了,调度器知道每个任务需要多少算力,schedutil就根据这个信息来调频。

它的优势:

  • 响应更快:调度器在分配任务时就知道负载,不需要等采样周期
  • 更精准:能区分「前台任务」和「后台任务」,优先保证交互流畅
  • 功耗更低:避免ondemand那种「过度调频」的问题

适用场景:Android设备、交互式应用、多任务场景

注意:需要内核支持SCHED_DEADLINECFS调度器,且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。调频策略的优化,说白了就是在「性能」和「功耗」之间做取舍。你想想看,是不是这个理?