1. 调度器功耗优化概述

为什么调度器会影响功耗?

这个问题,我刚开始做内核开发时也琢磨过。调度器不就是管着哪个任务上CPU跑吗?跟功耗有什么关系?

后来在项目里被现实狠狠教育了一顿。说白了,调度器决定了三件事:

  • CPU什么时候跑 —— 空闲还是忙碌
  • CPU跑多快 —— 低频还是高频
  • 任务在哪个CPU上跑 —— 要不要跨核迁移

这三件事,每件都直接跟功耗挂钩。你想想看,如果调度器让CPU频繁在空闲和忙碌之间切换,或者让任务在不同核之间跳来跳去,那功耗能不高吗?

核心观点:调度器是操作系统里对功耗影响最大的模块之一,因为它直接控制着CPU的“工作节奏”。

CPU idle状态与P-state基础

要理解调度器怎么影响功耗,得先搞清楚CPU的两种“省电模式”。

Idle状态(C-state)

CPU没事干的时候,会进入idle状态。不同的idle状态,省电程度不一样:

C-state名称特点退出延迟
C0运行态CPU正在干活0
C1Halt停止指令执行,但缓存保持几微秒
C2Stop-Clock关闭时钟,缓存保持几十微秒
C3Sleep关闭部分缓存,电压降低几百微秒
C6Deep 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(迁移频率, 缓存失效, 上下文切换)

这个模型虽然简单,但抓住了本质。调度器通过以下方式影响每一项:

  1. 负载均衡 —— 决定任务分布,影响空闲时间分布
  2. 频率调节 —— 决定P-state选择,影响运行功耗
  3. 任务调度策略 —— 决定迁移频率,影响迁移开销
  4. idle管理 —— 决定C-state选择,影响空闲功耗

举个例子,假设有两个任务,每个需要50%的CPU算力:

  • 方案A:两个任务放在同一个核上跑,另一个核完全空闲。空闲核可以进入C6深度睡眠,省电效果很好。
  • 方案B:两个任务各占一个核,每个核跑50%负载。两个核都只能进C1浅睡眠,总功耗反而更高。

你想想看,调度器选方案A还是方案B,功耗差距可能达到2倍以上。这就是为什么说调度器是功耗优化的关键。

关键洞察:调度器对功耗的影响,本质上是“时间-空间”的权衡。时间上,要合理安排任务的执行时机,让CPU有更多机会进入深度睡眠;空间上,要合理分布任务,减少不必要的核间迁移和缓存失效。

我个人在做功耗优化时,会先看调度器的这几个关键指标:

  • CPU空闲时间占比和分布
  • C-state进入/退出频率
  • P-state跳变频率
  • 任务迁移次数
  • 负载均衡的均匀程度

这些指标就像体检报告,能快速定位调度器层面的功耗问题。后面几章,我会逐一展开讲怎么优化这些指标。

一个小建议:刚开始做调度器功耗优化时,别急着改代码。先用trace工具把调度行为抓出来看看,搞清楚当前系统到底是怎么跑的。我见过太多人一上来就改参数,结果越改越糟。

好了,这一章先讲到这里。调度器影响功耗的底层逻辑,说白了就是:它决定了CPU什么时候干活、干多快、在哪干活。这三件事控制好了,功耗自然就降下来了。下一章,我们聊聊具体的trace工具和分析方法。