1. 调度器功耗优化概述
为什么调度器会影响功耗?
这个问题,我刚开始做内核开发时也琢磨过。调度器不就是管着哪个任务上CPU跑吗?跟功耗有什么关系?
后来在项目里被现实狠狠教育了一顿。说白了,调度器决定了三件事:
- CPU什么时候跑 —— 空闲还是忙碌
- CPU跑多快 —— 低频还是高频
- 任务在哪个CPU上跑 —— 要不要跨核迁移
这三件事,每件都直接跟功耗挂钩。你想想看,如果调度器让CPU频繁在空闲和忙碌之间切换,或者让任务在不同核之间跳来跳去,那功耗能不高吗?
核心观点:调度器是操作系统里对功耗影响最大的模块之一,因为它直接控制着CPU的“工作节奏”。
CPU idle状态与P-state基础
要理解调度器怎么影响功耗,得先搞清楚CPU的两种“省电模式”。
Idle状态(C-state)
CPU没事干的时候,会进入idle状态。不同的idle状态,省电程度不一样:
| C-state | 名称 | 特点 | 退出延迟 |
|---|---|---|---|
| C0 | 运行态 | CPU正在干活 | 0 |
| C1 | Halt | 停止指令执行,但缓存保持 | 几微秒 |
| C2 | Stop-Clock | 关闭时钟,缓存保持 | 几十微秒 |
| C3 | Sleep | 关闭部分缓存,电压降低 | 几百微秒 |
| C6 | Deep Sleep | 几乎完全断电,上下文保存 | 毫秒级 |
嗯,这里要注意:C-state越深,省电越多,但退出延迟也越大。调度器如果频繁让CPU在C0和深睡眠之间切换,那性能损失就大了。
我的经验:在手机项目上,我曾经遇到过一个问题:系统待机时功耗偏高。排查下来发现,有个后台服务每隔50ms就唤醒一次CPU,导致CPU根本进不了C2以上的深度睡眠。最后把那个服务的定时器合并了一下,待机功耗直接降了30%。
P-state(DVFS)
P-state是CPU在运行时的频率/电压组合。说白了就是:
- P0 —— 最高频率,性能最好,功耗最高
- P1, P2, ... —— 频率逐级降低,功耗也降低
调度器通过负载预测,来决定让CPU跑在哪个P-state。负载高就升频,负载低就降频。
避坑指南:我曾经见过一个案例,调度器频繁在P0和P3之间跳变,每秒钟跳几十次。每次跳变都有额外的能量开销,结果平均功耗反而比一直跑P1还高。这就是典型的“过度调频”问题。
调度器与功耗的关系模型
我习惯用一个简单的模型来理解调度器对功耗的影响:
总功耗 = 运行功耗 + 空闲功耗 + 迁移开销
运行功耗 = f(频率, 利用率, 任务类型)
空闲功耗 = f(空闲时间分布, C-state选择)
迁移开销 = f(迁移频率, 缓存失效, 上下文切换)
这个模型虽然简单,但抓住了本质。调度器通过以下方式影响每一项:
- 负载均衡 —— 决定任务分布,影响空闲时间分布
- 频率调节 —— 决定P-state选择,影响运行功耗
- 任务调度策略 —— 决定迁移频率,影响迁移开销
- idle管理 —— 决定C-state选择,影响空闲功耗
举个例子,假设有两个任务,每个需要50%的CPU算力:
- 方案A:两个任务放在同一个核上跑,另一个核完全空闲。空闲核可以进入C6深度睡眠,省电效果很好。
- 方案B:两个任务各占一个核,每个核跑50%负载。两个核都只能进C1浅睡眠,总功耗反而更高。
你想想看,调度器选方案A还是方案B,功耗差距可能达到2倍以上。这就是为什么说调度器是功耗优化的关键。
关键洞察:调度器对功耗的影响,本质上是“时间-空间”的权衡。时间上,要合理安排任务的执行时机,让CPU有更多机会进入深度睡眠;空间上,要合理分布任务,减少不必要的核间迁移和缓存失效。
我个人在做功耗优化时,会先看调度器的这几个关键指标:
- CPU空闲时间占比和分布
- C-state进入/退出频率
- P-state跳变频率
- 任务迁移次数
- 负载均衡的均匀程度
这些指标就像体检报告,能快速定位调度器层面的功耗问题。后面几章,我会逐一展开讲怎么优化这些指标。
一个小建议:刚开始做调度器功耗优化时,别急着改代码。先用trace工具把调度行为抓出来看看,搞清楚当前系统到底是怎么跑的。我见过太多人一上来就改参数,结果越改越糟。
好了,这一章先讲到这里。调度器影响功耗的底层逻辑,说白了就是:它决定了CPU什么时候干活、干多快、在哪干活。这三件事控制好了,功耗自然就降下来了。下一章,我们聊聊具体的trace工具和分析方法。