欢迎回来
登录你的知识库账户
忘记密码?
还没有账户?立即注册
创建账户
注册你的专属知识库
已有账户?去登录
找回密码
输入注册邮箱获取验证码
返回登录
请输入图片中的验证码以继续注册
加载中...
取消
新建收藏
手动添加你喜欢的内容
取消
编辑头像与昵称
上传新头像或修改你的显示昵称
支持 JPG/PNG,最大 2MB
取消

问题反馈

notebasewww.notebase.cn
控制台
内容库
动态
管理
账户
U
用户
--
在线
v0.8.7 · 知识库
笔记
KnowledgeBase
网络无边,知识有迹。
0笔记
0工具
30推荐

分类导航

按主题直达

编辑精选

站内用户贡献 · 真实笔记

最新收录

每日更新
继续浏览全部内容 →
>
笔记
0
加载中...
工具
0
此页用于记录用户反馈问题后的每一次改进
笔记用法

“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。

md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。

要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。

工具用法

在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。

要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。

工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。

隐藏笔记

写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。

适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。

数据安全

你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。

技术

全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。

理念

这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。

原则

不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。

更多

产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。

举报

如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。

趋势
// 点击导航加载发现
归档
// 归档为空
最近浏览
// 暂无浏览记录
发布
// 加载中...
用户发布
// 加载中...
用户管理
// 加载中...
访问统计
// 加载中...
内容审核
// 加载中...
个人信息
// 加载中...
返回首页

Stop Guessing, Start Profiling: Mastering Edge AI Performance and Power on Android

2026/7/4人工智能

好的,没问题。这篇原文讲的是 Android 端侧 AI 的性能和功耗分析,干货满满。我把它重新组织成一篇深度技术笔记,就像我自己踩过坑、调过参之后,写下来分享给团队同事的那种。我们开始吧。


先别急着调模型,先看看你的 App 在“吃”多少电

想象一下这个场景:你在工作站上花了几周时间优化模型,剪枝、量化、调参,一套组合拳下来,推理速度起飞了。你信心满满地把它部署到用户的 Android 手机上。结果呢?三分钟不到,App 开始掉帧,手机发烫,原本“快如闪电”的 AI 功能,现在输出一个 token 都费劲。

你是不是也遇到过?这其实就是撞上了 “功耗墙” (Power Wall)。

在端侧 AI 的世界里,性能从来不只是“模型跑多快”的问题,它更关乎“跑一次要耗多少电”和“会带来多少热量”。如果你开发端侧 AI 应用,却从没用过 Android Studio 的 Power Profiler(功耗分析器),那说句不好听的,你根本不是在开发,你是在“猜”。

为什么手机电池会“尿崩”?聊聊端侧 AI 的物理课

要真正搞懂功耗分析,我们不能只盯着“电池百分比”这个表象。当我们在手机上部署像 Gemini Nano 这样的端侧模型时(通过 AICore),本质上是在 CPU、GPU 和 NPU 之间编排一场高能耗的“舞蹈”。

热量、降频和“搬砖”的代价

在硬件层面,运行一个神经网络涉及数十亿次的乘加运算(MAC)。很多人以为瓶颈是算力(TFLOPS),但真相是,对于端侧 AI,最大的瓶颈往往是数据搬运的能量消耗。

每一次数据从 RAM 搬到处理器的寄存器里,都要耗电。当 NPU 使用率飙到 100% 时,它会产生高度集中的热量。如果手机的散热跟不上,Android 系统就会触发 热降频 (Thermal Throttling)。

这是系统层面的干预,内核会通过 动态电压频率调整 (DVFS) 来降低 SoC 的时钟频率。作为开发者,你看到的现象就是:App 跑了没几分钟,推理速度突然断崖式下跌,毫无道理。

Power Profiler 的价值就在于此:它能让你亲眼看到这种关联——能量消耗曲线飙升,紧接着性能曲线就跳水了。

端侧 AI 的“不可能三角”

每一个端侧 AI 开发者都在玩一个“三角博弈”,需要在三个相互制约的目标中寻找平衡:

  1. 精度 (Accuracy):更高的精度(比如 FP32)意味着更好的结果,但功耗也更大。
  2. 延迟 (Latency):用更快的硬件(GPU/NPU)能减少等待时间,但会产生更高的热量峰值。
  3. 能耗 (Energy):量化到 INT8 能降低功耗,但可能导致精度下降。

Profiling 的目标,就是找到那个 帕累托最优 (Pareto Optimal) 的点:一个让你的模型“精度够用”、“速度达标”、“散热良好”的配置,让用户用得爽。

新时代的架构:AICore 和 Gemini Nano

Google 通过 AICore 彻底改变了游戏规则。以前,开发者是把 .tflite 文件直接打进 APK 里的。这简直是效率灾难:每个 App 都有一份模型副本,导致磁盘空间严重浪费和内存重复分配。

AICore 是一个系统级的服务,它把端侧 AI 模型当作共享资源来管理。你可以把它想象成“AI 版的 Google Play Services”。

这个架构带来了三个巨大的好处:

  1. 模型可更新:Google 可以通过系统更新来更新 Gemini Nano 的权重,而你完全不需要动你的 APK。
  2. 内存效率:如果三个不同的 App 都在用 Gemini Nano,模型权重只需要加载到内存一次,然后通过只读内存映射 (read-only memory map) 共享给所有 App。
  3. 硬件抽象:就像 CameraX 抽象了不同的相机硬件一样,AICore 抽象了底层的 NPU。不管手机用的是高通 Hexagon DSP、Google Tensor TPU 还是 ARM Ethos NPU,你的 API 调用都是一致的。

搞清楚你的模型到底跑在哪个“引擎”上

要做有效的 Profiling,你必须知道你的模型正在哪个“引擎”上运行。如果在 Power Profiler 里看到推理期间 CPU 占用率很高,那说明有“泄漏”——你的模型很可能因为某个算子不被 NPU 支持,而回退到 CPU 上运行了。

  • NPU (神经网络处理单元):黄金标准。它利用大规模并行计算和本地化内存 (SRAM) 来最大限度地减少数据搬运,是最高效的选择。
  • GPU (图形处理器):很擅长 AI 需要的浮点运算,但功耗比 NPU 高得多。可以作为备选,但要小心热降频。
  • DSP (数字信号处理器):“永远在线”的哨兵。它处理低复杂度的任务(比如唤醒词检测),功耗可以忽略不计。

优化精要:量化和剪枝

如果你的 Power Profiler 显示“内存”轨道的功耗比“计算”轨道还高,那你就该关注 量化 (Quantization) 了。

把一个 32 位浮点数 (FP32) 从 RAM 搬到 NPU 是非常耗能的。通过把你的模型量化成 INT8 (8位整数),你不仅仅是将模型体积缩小了 4 倍,更重要的是,你降低了算术逻辑单元 (ALU) 里晶体管的“翻转率”。这让整个运算过程的能效提升了几个数量级。

剪枝 (Pruning) 则更进一步,它直接移除掉那些“死掉的”神经元。在 Power Profiler 里,成功的剪枝表现为功耗尖峰的“持续时间”变短了,因为 NPU 更快地完成了计算,然后迅速回到低功耗休眠状态 (C-state)。

动手实战:构建一个可 Profiling 的 AI 工作负载

光说不练假把式。要看到真实的效果,你需要一个可控的工作负载。下面我们来实现一个实时图像分类的 pipeline,用 TensorFlow Lite,并且专门设计了开关,让你可以在 Power Profiler 里切换 CPU 和 GPU,观察能量消耗的变化。

技术栈

这个例子会用 Hilt 做依赖注入,用 Kotlin 协程做异步编排,还有 TFLite GPU 委托。

1. AI 推理仓库 (Inference Repository)

这个类管理 TFLite 的生命周期。注意看这里使用了 Direct ByteBuffer 来避免昂贵的 JNI 内存拷贝——这是减少 CPU 开销的关键细节。

@Singleton
class InferenceRepository @Inject constructor(
    private val context: Context
) {
    private var interpreter: Interpreter? = null
    private var gpuDelegate: GpuDelegate? = null
    private val modelPath = "mobilenet_v2.tflite"

    fun initializeModel(useGpu: Boolean) {
        closeInterpreter()
        val options = Interpreter.Options().apply {
            if (useGpu) {
                // 关键点:把张量运算从 CPU 卸载到 GPU
                // 在 Power Profiler 里观察,CPU 轨道能耗下降,GPU 轨道能耗上升
                gpuDelegate = GpuDelegate()
                addDelegate(gpuDelegate)
            } else {
                setNumThreads(4) // 使用 CPU 多线程
            }
        }
        interpreter = Interpreter(loadModelFile(), options)
    }

    fun runInference(inputBuffer: ByteBuffer): FloatArray {
        val outputBuffer = Array(1) { FloatArray(1001) }
        interpreter?.run(inputBuffer, outputBuffer)
        return outputBuffer[0]
    }

    private fun loadModelFile(): ByteBuffer {
        val fileInputStream = FileInputStream(context.assets.openFd(modelPath))
        val fileChannel = fileInputStream.channel
        return fileChannel.map(
            FileChannel.MapMode.READ_ONLY,
            fileChannel.position(),
            fileChannel.size()
        )
    }

    fun closeInterpreter() {
        interpreter?.close()
        gpuDelegate?.close()
        interpreter = null
        gpuDelegate = null
    }
}

2. AI ViewModel

在端侧 AI 开发里,主线程是神圣不可侵犯的。我们用 Dispatchers.Default 来确保繁重的张量操作不会阻塞 UI 线程,导致界面卡顿。

@HiltViewModel
class AIViewModel @Inject constructor(
    private val repository: InferenceRepository
) : ViewModel() {

    private val _inferenceResult = MutableStateFlow("Ready")
    val inferenceResult: StateFlow<String> = _inferenceResult.asStateFlow()

    private val _isGpuEnabled = MutableStateFlow(false)
    val isGpuEnabled: StateFlow<Boolean> = _isGpuEnabled.asStateFlow()

    fun toggleHardware() {
        val useGpu = !_isGpuEnabled.value
        _isGpuEnabled.value = useGpu
        viewModelScope.launch(Dispatchers.Default) {
            repository.initializeModel(useGpu)
            // 这里可以触发一次预热推理,让 Power Profiler 的数据更干净
            // runInferenceOnSampleImage()
        }
    }

    // 模拟连续推理,制造可观测的功耗负载
    fun startBurstInference() {
        viewModelScope.launch(Dispatchers.Default) {
            repeat(100) {
                // 这里应该从 Camera 或 Bitmap 获取真正的图像数据
                val dummyInput = ByteBuffer.allocateDirect(1 * 224 * 224 * 3 * 4) // 假设输入是 224x224 RGB 图像
                val result = repository.runInference(dummyInput)
                _inferenceResult.value = "Inference $it: Top class index = ${result.indices.maxByOrNull { result[it] }}"
                // 稍微延迟一下,让功耗曲线看得更清楚
                delay(50)
            }
        }
    }

    override fun onCleared() {
        super.onCleared()
        repository.closeInterpreter()
    }
}

怎么用 Power Profiler 看效果?

  1. 打开 Android Studio,运行你的 App。
  2. 点击底部的 Profiler 标签。
  3. 在 Sessions 面板,选择你的设备和进程。
  4. 点击 Energy 时间线。
  5. 在 App 里,先点击 Toggle Hardware 按钮切换到 CPU 模式,然后点击 Start Burst Inference。
  6. 观察 CPU 轨道的能耗。你会看到一个明显的峰值,并且手机温度会逐渐上升。
  7. 等推理结束,再次点击 Toggle Hardware 切换到 GPU 模式,再次点击 Start Burst Inference。
  8. 观察能耗变化。你会看到 CPU 轨道几乎没动静了,但 GPU 轨道(如果有的话)或者总的能耗曲线,可能会在初期有一个更高的峰值(因为 GPU 启动有开销),但单个推理的能耗和完成速度可能更快。如果手机支持 NPU,并且你能通过 AICore 调用,那效果会更明显。

关键观察点:

  • CPU 模式:能耗曲线平缓但持续时间长,容易触发热降频,导致后期推理速度越来越慢。
  • GPU 模式:能耗曲线峰值更高,但单个推理耗时更短,总的能量消耗(曲线下的面积)可能更小。如果散热差,依然可能降频。
  • 理想状态 (NPU):能耗曲线峰值低,耗时极短,热量积累最慢。

总结

别再做“性能猜谜”了。Power Profiler 不是可选项,而是端侧 AI 开发的必备工具。它能帮你把抽象的“手机发烫”和“App 变慢”具体化为可见的能耗曲线和频率变化。下次再遇到性能问题,先别急着调模型结构,打开 Profiler,看看你的电都耗在哪了,是计算瓶颈还是数据搬运瓶颈?是 CPU 回退还是热降频?找到根因,你的优化才能事半功倍。

编写使用方法
Markdown 格式 · Ctrl+Enter 确定
新建笔记
预览
数据表格
点击单元格编辑 · Tab 移动
A1fx
Sheet1
BIH1H2≡🔗</>
隐私提醒

取消
编辑工具
取消