第3章:软件功耗模型

功耗模型这东西,说白了就是给软件的能量消耗画个像。你想想看,我们做嵌入式开发,代码跑起来到底吃了多少电?没有模型,你只能靠猜。我在项目中见过太多人,优化代码全凭感觉,结果功耗降了没降,自己都说不清楚。

这一章,我们来聊聊三种主流的建模方法。嗯,它们各有各的脾气,也各有各的适用场景。

3.1 功耗建模方法:从宏观到微观

建模这件事,我个人习惯先想清楚一个问题:我要多细的粒度?

如果你只想看整个系统跑了多少瓦,那用电流表一夹就行。但如果你想搞清楚哪段代码在偷电,那就得往细了挖。

常见的建模方法,大致分三个层次:

  • 黑盒模型:只看输入输出,不管内部。比如测一个函数执行前后的电流差。
  • 白盒模型:拆开看内部状态。比如每条指令、每个寄存器的翻转。
  • 灰盒模型:介于两者之间。只看关键事件,比如中断、DMA传输。

我在做一款低功耗蓝牙芯片时,一开始用的黑盒模型。后来发现,有些功耗波动根本解释不了。没办法,只能拆成白盒,一条指令一条指令地抠。那段时间,我盯着示波器的波形,眼睛都快瞎了。

核心观点:没有完美的模型,只有够用的模型。你的精度要求,决定了你的建模成本。

3.2 基于指令的功耗模型

这个模型,是嵌入式领域最经典的。它的思路很简单:每条指令消耗固定的能量

比如,ARM Cortex-M0 的一条 NOP 指令,可能消耗 0.1 nJ。而一条乘法指令,可能要 0.5 nJ。你把所有指令的能量加起来,就是这段代码的总功耗。

公式长这样:

E_total = Σ (N_i × E_i)

其中,N_i 是第 i 种指令的执行次数,E_i 是该指令的单次能耗。

听起来很完美,对吧?但实际用起来,坑不少。

我曾经踩过的坑:指令的能耗不是孤立的。流水线冲突、缓存命中与否,都会让实际能耗偏离模型值。有一次,我优化了一段循环,指令数减少了20%,但功耗只降了5%。查了半天,原来是缓存 miss 率上去了。

所以,基于指令的模型,适合做相对比较,不适合做绝对预测。你用它来对比两个算法谁更省电,挺好。但想精确算出电池能用多久,那得小心。

这里给个简单的示例,假设我们有个 RISC-V 内核:

// 假设每条指令能耗(单位:nJ)
// ADD: 0.2,  LD: 0.3,  ST: 0.35,  MUL: 0.6

int a = b + c;   // 1条ADD: 0.2 nJ
int d = a * 2;   // 1条MUL: 0.6 nJ
store(d, &buf);  // 1条ST:  0.35 nJ

// 总能耗 ≈ 0.2 + 0.6 + 0.35 = 1.15 nJ

你看,算起来很快。但别忘了,这还没算取指令、译码的开销。实际上,每条指令背后还有隐藏的能耗。

3.3 基于事件的功耗模型

这个模型,我更喜欢叫它「偷懒者的模型」。为什么?因为它不关心每条指令,只关心发生了什么事件

事件包括:

  • CPU 从睡眠唤醒
  • 外设开始一次 SPI 传输
  • DMA 搬运了一块数据
  • 定时器溢出

每个事件,都有一个固定的能耗标签。你统计事件发生的次数,就能估算总功耗。

举个例子,一个低功耗 MCU 的典型场景:

// 事件能耗表(单位:μJ)
// 唤醒事件: 5.0
// SPI发送1KB: 12.0
// 定时器中断: 0.8

// 假设一秒钟内:
// 唤醒 2 次: 2 × 5.0 = 10.0 μJ
// SPI 发送 1 次: 12.0 μJ
// 定时器中断 10 次: 10 × 0.8 = 8.0 μJ
// 总能耗 ≈ 30.0 μJ

这个模型的好处是,你不用关心 CPU 内部在干嘛。你只需要在关键路径上埋点,统计事件次数就行。

我记得有一次,帮客户优化一个物联网终端。他们用基于指令的模型算出来,功耗应该只有 50 μA。但实测是 200 μA。后来改用事件模型一查,发现一个 GPIO 中断被配置成了双边沿触发,每秒触发了上千次。这个事件,在指令模型里根本看不出来。

我的建议:在项目初期,用基于事件的模型快速定位大问题。到了优化后期,再用基于指令的模型精细调优。两个模型配合使用,效果最好。

3.4 两种模型的对比

这里我整理了一张表,方便你对比:

维度 基于指令的模型 基于事件的模型
粒度 细(指令级) 粗(事件级)
精度 高(理想条件下) 中(依赖事件定义)
实现难度 高(需要指令集数据) 低(埋点即可)
适用场景 算法优化、编译器调优 系统级功耗分析、低功耗调试
对硬件依赖 强(需要精确的指令能耗) 弱(只需要事件能耗)

你可能会问,那我到底该用哪个?

我的经验是:先粗后细。先用事件模型把大头抓住,再用指令模型去抠细节。别一上来就扎进指令级,那样容易迷失方向。

一句话总结:指令模型让你知道「代码怎么省电」,事件模型让你知道「系统为什么费电」。两个都学会,你才算真正入了功耗分析的门。

好了,这一章就到这里。下一章,我们会聊聊具体的功耗测量工具和方法。到时候,我会拿一个真实的项目案例,手把手带你走一遍。