图像超分端侧推理功耗与温控平衡实战【鸿蒙心迹】

摘要
端侧超分(Super Resolution)功能上线后,连续处理多张老照片或在滑动预览场景中挂载超分,手机后盖明显发烫、约 30 秒后预览掉帧、超分输出反而变慢——根因是 NPU 持续满负载触发系统温控降频,撞上了端侧 AI 推理最典型的"功耗墙"。本文基于 HarmonyOS 的 @kit.CoreVisionKit 超分能力,结合 @ohos.thermal 温控订阅与 @ohos.batteryInfo 充电状态感知,落地三招:帧率节流、温控订阅降档、分片推理。实测连续处理 50 张 1080p 图片,机身温度峰值从 46℃ 降到 39℃,全程无掉帧,平均单张耗时 230ms。文中给出可直接复用的 TypeScript 代码骨架、整体调度流程图、温控档位与并发度对照表,以及上线前必查的实战清单。
目录
一、背景与痛点
上篇讲了端侧超分怎么接入,但功能上线后我碰到更隐蔽的问题:用户连续放大十几张老照片,或把超分挂在有滑动预览的场景里,手机后盖明显发烫,约 30 秒后预览开始掉帧,超分输出反而变慢。查日志发现是 NPU 持续满负载触发了系统温控(thermal)降频——这正是端侧 AI 推理最典型的"功耗墙"。
问题本质不是模型不准,而是没有给推理任务做节流和温控感知。超分是重负载算子,若在主线程或高优先级循环里无脑狂跑,不仅伤体验,长期还会加速电池老化、招来投诉。本文把我在项目里落地的三招——帧率节流、温控订阅降档、分片推理——完整讲清。
二、环境与能力规格
| 维度 | 规格 |
|---|---|
| 超分能力 | @kit.CoreVisionKit 的 imageSuperResolution(API 26) |
| 温控接口 | @ohos.thermal 的 ThermalManager,订阅 levelChange |
| 功耗接口 | @ohos.batteryInfo 读取电量/充电状态 |
| 运行位置 | 端侧 NPU/XPU,数据不出设备 |
| 适配建议 | 推理放 TaskPool,避免阻塞 UI 线程 |
系统温控分 0~4 级(NORMAL/LOW/WARNING/CRITICAL/EMERGENCY),我们只在 NORMAL/LOW 跑满速,WARNING 起主动降速。
三、核心代码(可复用骨架)
import { imageSuperResolution } from '@kit.CoreVisionKit';
import { thermal } from '@ohos.thermal';
import { batteryInfo } from '@ohos.batteryInfo';
import { taskpool } from '@kit.ArkTS';
// 1) 订阅温控,动态决定推理并发度
let thermalLevel = 0; // 0=NORMAL
thermal.on('levelChange', (level: number) => {
thermalLevel = level;
console.info(`[SR] thermal level -> ${level}`);
});
// 2) 根据温控档位推导每批最多处理几张
function batchSizeByThermal(): number {
if (thermalLevel <= 1) return 4; // NORMAL/LOW:满速
if (thermalLevel === 2) return 2; // WARNING:减半
return 1; // CRITICAL+:单张串行
}
// 3) 是否处于充电状态(充电时温控更宽松,可放开并发)
function isCharging(): boolean {
return batteryInfo.chargingStatus === batteryInfo.ChargingStatus.ENABLE;
}
// 4) 综合温控与充电状态,得到最终并发度
function effectiveConcurrency(): number {
const base = batchSizeByThermal();
return isCharging() ? Math.min(base + 1, 4) : base;
}
// 5) 页面级单例 Analyzer,避免反复 create/destroy 带来的额外发热
let analyzer: imageSuperResolution.ImageSRAnalyzer | null = null;
async function getAnalyzer(): Promise<imageSuperResolution.ImageSRAnalyzer> {
if (analyzer === null) {
analyzer = await imageSuperResolution.ImageSRAnalyzer.create();
}
return analyzer;
}
// 6) 单张超分放到 TaskPool,远离 UI 线程
async function srOne(visionImage: object): Promise<ArrayBuffer> {
return await taskpool.execute(async () => {
const sr = await getAnalyzer();
return await sr.process(visionImage);
});
}
// 7) 分片推理:按当前并发度分批处理,批间让出调度
async function srBatch(images: object[]): Promise<ArrayBuffer[]> {
const results: ArrayBuffer[] = [];
let index = 0;
while (index < images.length) {
const size = effectiveConcurrency();
const slice = images.slice(index, index + size);
const part = await Promise.all(slice.map((img) => srOne(img)));
results.push(...part);
index += size;
// 批间短暂让出,给系统降温与调度留出窗口
await new Promise<void>((resolve) => setTimeout(resolve, 16));
}
return results;
}
// 8) 页面销毁时释放单例并取消订阅,避免泄漏
function releaseSR(): void {
thermal.off('levelChange');
if (analyzer !== null) {
analyzer.destroy();
analyzer = null;
}
}
四、整体流程与温控档位说明
先看整体调度流程:从图片入队到按温控档位分批推理,再到批间让出与资源释放。
温控档位与策略对应关系如下,可直接对照代码里的 batchSizeByThermal():
| 温控档位 | level | 并发度 | 策略说明 |
|---|---|---|---|
| NORMAL | 0 | 4 | 满速运行,正常批量修复 |
| LOW | 1 | 4 | 仍满速,但已接近阈值需关注 |
| WARNING | 2 | 2 | 并发减半,优先保体验 |
| CRITICAL | 3 | 1 | 单张串行,避免持续满负载 |
| EMERGENCY | 4 | 1 | 单张串行,必要时提示用户暂停 |
五、运行效果与踩坑
- 踩坑 1:Analyzer 反复 create/destroy 反而更热。 我一开始每张都新建,初始化开销比推理还大。改成"页面级单例 + 用完复用"后,单张平均耗时从 480ms 降到 210ms,温升更平缓。
- 踩坑 2:thermal 回调不在主线程。 直接拿 level 改 UI 状态会崩,必须用
taskpool或@State配合切回。 - 踩坑 3:充电时温控更宽松。 实测插电状态同一负载 level 长期停在 1,所以"批量修复相册"功能我默认提示用户插电运行,体验最佳。
- 效果: 连续处理 50 张 1080p 图,机身温度峰值从 46℃ 降到 39℃,无掉帧,平均单张 230ms。
六、小结与适用边界
端侧超分不是"调通 API 就完事",功耗与温控是上线前必须过的关。核心思路:推理异步化 + 温控感知降档 + 充电视为加速条件。适合老照片修复、相册实时预览;不适合对单张时延极度敏感、且设备无 NPU 的低端机。
七、实战清单(可直接抄)
- 推理统一放 TaskPool,页面级单例复用 Analyzer,严禁逐张 create/destroy,单张耗时能从 480ms 压到 210ms。
- 启动即订阅
@ohos.thermal的levelChange,WARNING 起自动降并发(4→2→1),把温升主动权交给系统。 - 批量任务主动提示用户插电运行,实测插电时温控档位更宽松、连跑不掉速。
- 上线前用 50 张图连跑画温度曲线,峰值控在 40℃ 内、全程无掉帧再发布。
- 低端无 NPU 设备提供"关闭超分"开关,避免负体验,也防止无谓耗电。
说到底,端侧 AI 的体验门槛从来不是"能不能跑",而是"跑得稳不稳、凉不凉"。把温控和功耗当成一等公民,超分才从 Demo 变成能天天用的功能。
更多推荐




所有评论(0)