ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

旧安卓手机部署大模型实战:OlliteRT 端侧推理与性能调优

旧安卓手机部署大模型实战:OlliteRT 端侧推理与性能调优 旧手机吃灰这件事估计每个人家里都能翻出两三台。前阵子我整理抽屉翻出来一台骁龙 855 的老机器屏幕有点老化电池也不太行了但 CPU 和内存还算能打。当时第一反应是拿去换不锈钢盆后来转念一想这玩意的算力其实比很多开发板强不少为什么不拿来跑个大模型试试于是就有了这次折腾——用 OlliteRT 在旧安卓机上部署大模型顺便把性能调优的坑踩了一遍。这篇文章就是整个过程的完整记录从环境准备、模型选型、部署步骤到性能调优全部是实测出来的经验不是纸上谈兵。如果你手里也有闲置的安卓设备想让它发挥点余热或者你对端侧大模型部署感兴趣这篇内容应该能帮你少走不少弯路。1. 为什么要在旧手机上跑大模型1.1 端侧推理这件事到底值不值得做先说结论值得但要看你的预期是什么。很多人一听到手机跑大模型第一反应是这不是找罪受吗。确实如果你指望在手机上跑出云端 API 那种流畅体验那趁早放弃。但端侧推理有它不可替代的价值——数据不出设备、离线可用、没有网络延迟、不消耗 token 费用。这几个优势在特定场景下非常关键比如隐私敏感的个人助手、网络不稳定的户外环境、或者单纯想研究模型推理机制的开发者。从技术角度看现在安卓设备的硬件条件比几年前好太多了。骁龙 8 系芯片的 NPU 算力已经相当可观内存普遍 8GB 起步UFS 3.1 的存储读写速度也够用。即便是几年前的旧旗舰跑量化后的小参数模型完全没问题。我这次用的骁龙 855 配合 8GB 内存跑 1B 到 3B 参数的量化模型推理速度虽然谈不上快但日常问答、文本摘要这类任务是可以接受的。另外一个容易被忽略的点是端侧部署的过程本身就是一次很好的学习机会。你会接触到模型量化、推理框架、算子优化、内存管理这些在云端部署时往往被封装掉的东西。把这些搞明白对理解大模型的运行机制帮助很大。1.2 OlliteRT 解决了什么痛点在 OlliteRT 出现之前安卓端跑大模型主要有几条路一是用 TensorFlow Lite 自己转换模型但支持的大模型架构有限转换过程也麻烦二是用 MLC LLM 这类方案效果不错但编译链复杂对新手不太友好三是直接调云端 API那就失去了端侧的意义。OlliteRT 的思路不太一样它把模型加载、推理调度、内存管理这些脏活累活封装起来对外暴露相对简洁的接口。你可以把它理解成安卓端的推理运行时类似桌面端的 Ollama 那种定位。它支持 GGUF 格式的量化模型这意味着你可以直接用社区里现成的量化模型文件不需要自己从头转换。对于想快速验证想法的人来说这个门槛降低了很多。它主要解决三个问题第一是模型格式兼容GGUF 是目前端侧量化模型的主流格式生态最丰富第二是硬件加速适配能根据设备能力自动选择 CPU、GPU 或 NPU 后端第三是内存管理大模型加载对内存压力很大OlliteRT 在内存分配和回收上做了不少优化避免推理过程中被系统杀掉。1.3 旧手机作为推理设备的真实定位得把预期摆正。旧手机跑大模型定位是轻量级本地推理节点不是替代云端服务。适合的任务包括短文本问答、简单的情感分析、关键词提取、文本分类、小规模的翻译。不适合的任务包括长文档理解、复杂推理、代码生成、多轮长对话。我实测下来1B 参数的模型在骁龙 855 上生成速度大概在每秒 5 到 8 个 token3B 模型降到每秒 2 到 4 个 token。这个速度用来做交互式对话会有点卡但做批处理任务比如一次性处理一批文本就完全够用。所以关键是想清楚你的使用场景别拿它去做它不擅长的事。还有一点旧手机的散热是个大问题。持续推理会让 SoC 温度快速上升然后触发降频速度断崖式下跌。所以如果你要做长时间推理任务散热措施必须考虑这个后面会详细讲。2. 部署前的环境准备与模型选型2.1 设备要求与系统版本检查不是所有安卓机都能跑。先说硬性门槛系统版本建议 Android 10 及以上因为 OlliteRT 依赖的一些底层 API 在低版本上不可用。内存最低 6GB推荐 8GB 以上因为模型加载后还要留出足够的运行内存否则系统会频繁杀后台。存储空间至少预留 10GB量化模型文件虽然不大但加上运行时缓存和日志空间消耗比想象中多。CPU 架构方面arm64-v8a 是必须的32 位设备直接放弃。如果你的设备支持 GPU 加速比如 Adreno 或 Mali 的较新系列推理速度会有明显提升。NPU 支持则要看具体芯片和 OlliteRT 的适配情况目前覆盖度还在完善中不要抱太高期望。检查设备信息可以用这几条命令通过 adb 执行adb shell getprop ro.build.version.release adb shell getprop ro.product.cpu.abi adb shell cat /proc/meminfo | head -5 adb shell df -h /data第一条看系统版本第二条看 CPU 架构第三条看内存第四条看存储剩余空间。这几项确认没问题再往下走不然装到一半发现不兼容白折腾。2.2 模型格式与量化等级怎么选GGUF 格式的量化等级很多常见的有 Q4_0、Q4_K_M、Q5_K_M、Q8_0 等。数字代表量化位数字母代表量化策略。简单理解位数越低模型越小、速度越快但精度损失越大位数越高效果越好但占用资源越多。对于旧手机我的建议是优先选 Q4_K_M。这个等级在精度和体积之间平衡得比较好4 位量化配合 K 系列的分组策略实际效果比早期的 Q4_0 好不少。如果你设备内存紧张可以退到 Q4_0如果内存充裕且追求效果可以上 Q5_K_M但速度会慢一些。模型参数规模的选择参考这个表参数规模量化后体积内存占用骁龙 855 生成速度适用场景0.5B约 400MB约 1GB15-20 token/s分类、提取1B约 700MB约 1.5GB5-8 token/s问答、摘要3B约 2GB约 3GB2-4 token/s复杂问答7B约 4GB约 6GB1 token/s 以下不推荐这个数据是我实测的不同设备会有差异但量级参考价值是有的。7B 模型在旧手机上基本没有实用价值加载都费劲别浪费时间。2.3 模型文件的获取与校验模型文件从社区平台下载选 GGUF 格式的对应量化版本。下载完成后一定要校验文件完整性因为大文件下载中断导致损坏的情况很常见。用 sha256 校验sha256sum model-q4_k_m.gguf对比下载页面提供的哈希值一致才能用。我踩过一次坑文件下载到 99% 断了重新下载后没校验结果加载时报了一堆莫名其妙的错排查了半天才发现是文件损坏。文件放置位置也有讲究。建议放在应用私有目录下避免被其他应用或系统清理误删。路径类似/data/data/你的包名/files/models/。如果模型文件较大注意安卓对单个应用存储的限制必要时申请外部存储权限。3. OlliteRT 的集成与部署实操3.1 项目依赖配置与权限声明集成 OlliteRT 的第一步是把依赖加进项目。在build.gradle里添加dependencies { implementation com.ollitert:runtime:1.0.0 implementation com.ollitert:backend-cpu:1.0.0 implementation com.ollitert:backend-gpu:1.0.0 }CPU 后端是必选的GPU 后端根据设备情况选装。如果你的应用要上架应用商店注意 GPU 后端可能会增加包体积可以考虑用动态下发的方式。权限方面至少需要声明这几项uses-permission android:nameandroid.permission.INTERNET / uses-permission android:nameandroid.permission.READ_EXTERNAL_STORAGE / uses-permission android:nameandroid.permission.WAKE_LOCK /INTERNET 权限用于模型下载如果做在线下载READ_EXTERNAL_STORAGE 用于读取模型文件WAKE_LOCK 用于防止推理过程中设备休眠。注意 Android 13 及以上存储权限改成了细分的媒体权限读模型文件建议用应用私有目录避免权限适配的麻烦。3.2 模型加载与推理接口调用OlliteRT 的接口设计比较直观核心就几个方法。先初始化运行时OlliteRuntime runtime new OlliteRuntime.Builder() .setBackend(OlliteBackend.CPU) .setThreads(4) .setContextSize(2048) .build();setThreads设置推理线程数一般设成 CPU 大核数量骁龙 855 是 4 个大核所以设 4。setContextSize是上下文窗口大小越大占用内存越多2048 对大多数场景够用。加载模型Model model runtime.loadModel(/data/data/包名/files/models/model-q4_k_m.gguf);这一步比较耗时1B 模型大概需要 3 到 5 秒建议放在后台线程执行同时给用户一个加载进度提示。推理调用InferenceRequest request new InferenceRequest.Builder() .setPrompt(你好请介绍一下你自己) .setMaxTokens(256) .setTemperature(0.7f) .setTopP(0.9f) .build(); InferenceResult result model.infer(request); String output result.getText();maxTokens控制生成的最大长度别设太大旧手机上生成越长越容易触发降频。temperature和topP是采样参数调低会让输出更确定调高更随机。3.3 首次运行必做的冒烟测试部署完别急着做复杂功能先跑一个最小验证。我一般会做三步冒烟测试第一步加载模型确认不报错记录加载耗时。如果加载就失败多半是模型文件损坏或路径不对。第二步跑一个固定输入的推理比如11 等于几确认能正常输出。这一步验证推理链路是通的。第三步连续跑 10 次推理观察内存占用和温度变化。这一步能提前发现内存泄漏和散热问题。for (int i 0; i 10; i) { long start System.currentTimeMillis(); InferenceResult r model.infer(request); long cost System.currentTimeMillis() - start; Log.d(OlliteRT, 第 i 次推理耗时: cost ms); }把每次耗时打出来如果耗时逐次递增说明有内存或散热问题需要进一步排查。这个测试花不了几分钟但能帮你避开后面很多坑。4. 性能调优的实战手段4.1 线程数与批处理大小的调参逻辑线程数不是越多越好。安卓的 CPU 调度比较复杂大核小核混在一起线程开太多反而会因为调度开销导致性能下降。我的经验是线程数设成物理大核数量骁龙 855 是 4 个骁龙 8 Gen 1 是 4 个1 个 X2 超大核加 3 个大核设 4 到 5 比较合适。批处理大小batch size在端侧一般设 1因为端侧推理通常是交互式的没有批量请求。但如果你做的是批处理任务可以适当调大不过要注意内存占用会成倍增加。实测 1B 模型 batch size 从 1 调到 4内存占用增加约 800MB速度提升约 30%这个取舍要看设备内存情况。还有一个容易被忽略的参数是 KV Cache 的大小。它和上下文窗口相关上下文设得越大KV Cache 占用越多。如果内存紧张可以适当减小上下文窗口比如从 2048 降到 1024内存能省下几百 MB。4.2 GPU 加速的开启条件与实测效果GPU 加速不是所有设备都能开。OlliteRT 的 GPU 后端目前主要支持 Adreno 和 Mali 的较新系列具体支持列表要看官方文档。开启方式OlliteRuntime runtime new OlliteRuntime.Builder() .setBackend(OlliteBackend.GPU) .setGpuLayers(20) .build();setGpuLayers控制有多少层跑在 GPU 上设得越多 GPU 负载越高。不是所有层都适合放 GPU因为 CPU 和 GPU 之间的数据传输有开销层数设太多反而会变慢。我的经验是从 10 层开始试逐步往上加找到速度拐点。实测下来骁龙 855 的 Adreno 640 开启 GPU 加速后1B 模型生成速度从每秒 6 token 提升到每秒 9 token 左右提升约 50%。但功耗和发热也明显增加持续推理 10 分钟后降频速度反而掉到每秒 4 token。所以 GPU 加速适合短时突发任务不适合长时间持续推理。4.3 内存优化与后台保活策略内存是旧手机跑大模型最大的瓶颈。几个优化手段第一用largeHeap声明在 manifest 里加上android:largeHeaptrue能拿到更大的堆内存上限。但这不是万能药系统内存紧张时该杀还是杀。第二及时释放不用的资源。推理完成后调用model.release()释放模型占用的内存虽然下次加载又要花时间但能避免被系统杀掉。第三用前台服务保活。把推理任务放在前台服务里配合常驻通知能大幅降低被杀的几率。但要注意前台服务需要用户可见的通知不能偷偷跑。// 前台服务示例 startForeground(1, buildNotification(模型推理中));第四监控内存压力。用onTrimMemory回调感知系统内存状态在内存紧张时主动释放缓存。Override public void onTrimMemory(int level) { if (level TRIM_MEMORY_RUNNING_LOW) { model.clearCache(); } }4.4 散热控制与持续推理的稳定性散热是旧手机跑大模型绕不开的问题。骁龙 855 持续满载推理10 分钟左右 SoC 温度就能到 45 度以上然后开始降频。几个应对办法物理散热最直接。加个散热背夹或者把手机放在金属散热板上能明显延缓降频。我实测加了散热背夹后持续推理 30 分钟速度只下降 20%不加的话 10 分钟就掉一半。软件层面控制推理节奏。不要连续不断地推理中间加个短暂间隔让 SoC 有时间散热。比如每推理 5 次休息 2 秒虽然总吞吐下降但能维持更长时间。降低推理负载。减小 maxTokens降低上下文窗口关闭 GPU 加速这些都能减少发热。如果任务对速度不敏感可以把线程数降到 2牺牲速度换稳定性。监控温度可以用adb shell cat /sys/class/thermal/thermal_zone*/temp不同设备路径可能不同找到 CPU 对应的那个 zone 就行。温度超过 42 度就该考虑降负载了。5. 踩过的坑与排查实录5.1 模型加载失败的几种典型原因模型加载失败是最常见的坑原因五花八门。我遇到过的有文件路径错误。安卓的路径和桌面不一样/sdcard/和/storage/emulated/0/是同一个位置但应用私有目录是/data/data/包名/别搞混。用context.getFilesDir()获取私有目录路径最稳妥。文件权限不足。放在外部存储的模型文件需要运行时申请读取权限。Android 11 及以上还要处理分区存储建议直接放私有目录省事。模型格式不匹配。GGUF 有多个版本老版本 OlliteRT 可能不支持新版本 GGUF。确认模型文件的 GGUF 版本和运行时兼容。内存不足。加载 3B 模型需要约 3GB 可用内存如果设备后台应用太多加载会失败。加载前先清理后台或者用ActivityManager检查可用内存。排查时先看日志OlliteRT 的报错信息还算详细会提示具体是哪个环节出的问题。如果日志看不懂用最小模型0.5B测试排除是模型本身的问题还是环境问题。5.2 推理速度突然变慢的排查链路推理速度突然变慢排查要按顺序来先看温度。温度过高触发降频是最常见原因。查温度如果超过 42 度基本就是散热问题。再看内存。内存不足会触发频繁 GC拖慢推理。用adb shell dumpsys meminfo 包名看内存占用如果接近上限就是内存问题。然后看线程。线程数设置不合理或者被系统限制也会变慢。检查setThreads的值以及系统是否对后台线程做了限制。最后看模型。如果换了模型之后变慢可能是模型量化等级变了或者模型本身有问题。换回之前的模型对比测试。这个排查顺序是从最常见到最罕见能帮你快速定位问题。别一上来就怀疑代码大部分性能问题都是环境和资源导致的。5.3 应用被系统杀后台的应对旧手机内存本来就紧张跑大模型时应用被系统杀掉是家常便饭。应对手段前台服务是标配。把推理任务放前台服务配合常驻通知能大幅降低被杀概率。通知内容要如实说明别搞欺骗性文案。android:persistenttrue这个属性对普通应用无效别指望它。它只对系统应用生效。JobScheduler或WorkManager适合做延迟任务但不适合实时推理因为调度时机不可控。最根本的办法还是降低内存占用。用更小的模型减小上下文窗口及时释放资源。内存占用降下来被杀的概率自然就低了。如果实在保不住就做断点续推。把推理状态持久化被杀后重启能接着跑。这个实现起来麻烦但对付旧手机这种不稳定环境很有效。6. 端侧推理的边界与后续玩法6.1 旧手机跑大模型的能力天花板得承认旧手机跑大模型有明确的天花板。参数规模上3B 基本是上限7B 以上没有实用价值。速度上交互式对话体验较差批处理任务尚可。稳定性上长时间推理受散热和内存限制需要精心调优。但这个天花板不是固定的。随着量化技术改进、推理框架优化、硬件加速适配完善同样的硬件能跑的模型会越来越大速度会越来越快。我这次用的 OlliteRT 版本比半年前的老版本同样模型速度提升了约 40%这就是软件优化的价值。所以别因为现在跑不动 7B 就放弃把环境搭好等框架更新了直接换模型就行。端侧推理这个方向软件优化的空间还很大。6.2 从单机推理到多设备协同单台旧手机能力有限但如果你有几台闲置设备可以考虑协同推理。思路是把模型分层不同设备跑不同的层通过网络传递中间结果。这个方案在学术上有研究工程实现也有开源项目但复杂度较高适合折腾型玩家。更实际的玩法是做任务分发。一台设备做推理其他设备做数据预处理和后处理各司其职。比如一台旧手机专门跑模型另一台做 OCR 和文本清洗组合起来能完成更复杂的任务。还有一种玩法是模型蒸馏。用云端大模型生成训练数据在旧手机上微调小模型让小模型在特定任务上达到接近大模型的效果。这个路线对数据要求高但效果上限也高。6.3 这套方案还能迁移到哪些场景旧手机跑大模型的这套方法可以迁移到不少场景。比如电视盒子很多盒子的硬件配置和旧手机差不多刷个系统就能跑推理。比如开发板RK3588 这类板子性能比旧手机还强部署方式类似。比如车机如果车机是安卓系统且能装应用也能跑端侧模型。核心思路是一样的GGUF 量化模型加端侧推理框架根据设备能力调整参数。把这套流程跑通一次换设备就是改改配置的事。我在实际使用中最大的体会是端侧推理的价值不在于性能多强而在于它把 AI 能力带到了没有网络、不方便上云的环境里。旧手机只是一个载体真正有意思的是这种把智能放到边缘的思路。手里有闲置设备的不妨试试折腾的过程本身就挺有收获。
返回列表