1. 为什么端侧大模型推理绕不开高通NPU过去一年端侧跑大模型从能不能跑变成了怎么跑得又快又省电。我接触过不少团队模型在服务器上跑得好好的一挪到手机上就傻眼——延迟高、发热大、掉电快。问题的核心在于大多数人第一反应是用CPU硬扛或者简单调个GPU但真正能让大模型在移动端稳定输出的其实是NPU这条路径。而在安卓阵营里高通的Hexagon NPU是绕不开的存在搭载骁龙8 Gen系列和8s Gen系列的设备保有量摆在那里你不适配它等于放弃了最大的用户盘子。这篇内容我想聊的是高通NPU上跑大模型推理框架的技术调研和横向对比。具体来说会涉及QNNQualcomm Neural Network这套官方推理栈、Hexagon SDK的底层能力、不同框架比如ONNX Runtime、TFLite、MNN、llama.cpp的QNN后端等在高通NPU上的适配现状以及实际部署时会遇到的那些文档里不写但一定会踩的坑。适合谁看如果你正在做端侧AI应用、想把大模型塞进安卓设备、或者单纯想搞清楚高通NPU到底能干什么这篇应该能帮你省下不少试错时间。先给一个结论性的判断目前高通NPU跑大模型成熟度最高的路径是QNN 量化后的模型框架层面ONNX Runtime和llama.cpp的QNN后端相对可用但离开箱即用还有距离。下面我把调研过程拆开讲。2. Hexagon NPU的硬件底子决定了框架能做什么2.1 Hexagon架构的几代演进与算力边界要理解框架为什么这么设计得先知道Hexagon NPU的硬件特性。高通的Hexagon不是一块单纯的矩阵加速器它是一个异构计算单元包含标量单元、向量单元HVX和张量加速器。从骁龙855时代的Hexagon 690开始高通就在往里面加张量加速能力到骁龙8 Gen 1的Hexagon 780、8 Gen 2的Hexagon 790再到8 Gen 3的Hexagon 800系列张量核心的占比越来越大。关键点在于Hexagon的向量单元HVX支持INT8和INT16的定点运算张量加速器则针对INT8和部分INT4做了优化。这意味着什么意味着你想让大模型在NPU上跑得动量化几乎是必须的。FP16在部分场景能跑但吞吐和功耗都不理想。我实测过同一个7B模型FP16在NPU上基本跑不起来INT8量化后能到可用的程度INT4则进一步把内存占用压下来但精度损失需要评估。这里有个容易被忽略的细节不同代际的Hexagon其张量核心的指令集和吞吐是不一样的。骁龙8 Gen 2和8 Gen 3的NPU算力差距在高负载大模型推理上体现得很明显。所以做框架选型时不能只看支持高通NPU这个笼统的描述要具体到芯片型号和Hexagon版本。2.2 QNN在软件栈里的位置QNN是高通官方提供的神经网络推理框架它向下对接Hexagon NPU、Adreno GPU和CPU向上提供统一的API。你可以把它理解成高通版的推理引擎抽象层。它的核心组件包括QNN Backend后端、QNN Context上下文、QNN Graph计算图等。QNN的工作流程大致是你把训练好的模型通常是ONNX或TFLite格式通过QNN Converter转成QNN的模型格式然后在运行时用QNN Backend加载并执行。Converter这一步会做图优化、算子融合、量化等操作。这里的关键是QNN Converter对算子的支持是有限的不是所有ONNX算子都能转过去。我遇到过不少模型卡在Converter这一步就过不去报unsupported operator。提示在动手之前先去高通官方文档查一下当前QNN版本支持的算子列表。这个列表每个版本都在变而且不同Hexagon架构支持的算子也不完全一样。2.3 为什么不能直接用CUDA那套思路很多人从服务器端转过来习惯性地想找高通版的cuDNN或者高通版的TensorRT。QNN确实在定位上类似TensorRT但生态成熟度差得远。CUDA生态有十几年的积累算子库、工具链、社区支持都很完善。QNN这边文档相对零散示例代码不多遇到问题主要靠官方论坛和高通开发者支持。另一个差异是调试手段。在服务器上你可以用nsight、nvprof各种工具看kernel执行情况。高通这边Hexagon SDK提供了一些profiling工具但用起来门槛高而且很多细节不对外开放。这导致性能调优时你往往只能靠改参数-测延迟这种黑盒方式。3. 主流推理框架在高通NPU上的适配现状3.1 ONNX Runtime的QNN Execution ProviderONNX Runtime是目前端侧推理框架里对高通NPU支持相对最好的一个。它通过QNN Execution ProviderEP把计算图的一部分或全部offload到Hexagon NPU上执行。用起来的方式是在创建InferenceSession时指定QNN EP并配置相关参数。实际用下来ONNX Runtime QNN EP的优点是接入成本低如果你已经有ONNX模型改几行代码就能试。但问题也很明显第一算子覆盖不全遇到不支持的算子会fallback到CPU导致性能断崖式下降第二量化流程不够顺滑你需要先用QNN的工具做量化再喂给ONNX Runtime第三版本兼容性坑多ONNX Runtime版本、QNN SDK版本、设备固件版本三者之间的匹配关系需要仔细核对。我踩过的一个坑是在某台骁龙8 Gen 2设备上ONNX Runtime 1.16 QNN SDK 2.18能跑通但换成1.17就报错。后来查下来是QNN EP的接口变了。所以建议锁定版本组合不要随意升级。3.2 llama.cpp的QNN后端llama.cpp这两年在端侧大模型圈子里很火它的QNN后端也在逐步完善。相比ONNX Runtimellama.cpp的优势是专门为大语言模型做了优化支持GGUF格式的量化模型内存管理更精细。它的QNN后端目前还在活跃开发中社区提交比较频繁。我用llama.cpp的QNN后端跑过Qwen2和Llama3的量化版本整体体验是小模型1B-3B跑起来比较顺7B以上对内存和NPU算力要求高需要设备有足够的RAM。另外llama.cpp的QNN后端对KV Cache的处理还在优化中长上下文场景下性能衰减比较明显。3.3 TFLite与MNN的NPU委托TFLite通过NNAPIAndroid Neural Networks API间接调用高通NPU。NNAPI是高通、谷歌等联合推的安卓标准理论上写一次代码能跑在多家NPU上。但实际效果嘛……NNAPI的抽象层太厚很多高通NPU的特性用不上性能不如直接走QNN。而且NNAPI的算子支持也是参差不齐大模型这种复杂结构很容易碰到不支持的算子。MNN是阿里开源的推理框架它对高通NPU也有支持主要通过QNN后端。MNN的优点是轻量、部署简单在国内社区有一定用户基础。但在大模型场景下MNN的生态和工具链不如ONNX Runtime完善。3.4 框架对比一览框架高通NPU支持方式大模型适配度接入难度社区活跃度ONNX RuntimeQNN EP中等低高llama.cppQNN后端较高中高TFLiteNNAPI低低中MNNQNN后端中等中中QNN原生直接调用高高低这张表是我基于实际调研和测试给出的主观评价。接入难度低不代表效果好QNN原生接入难度最高但能榨出最多性能。选哪个取决于你的团队能力和项目需求。4. 模型量化NPU推理的命门4.1 为什么INT8是起步线前面提过Hexagon NPU的张量核心主要针对INT8和INT4优化。FP16虽然部分支持但吞吐上不去。所以模型量化不是可选项而是必选项。量化的本质是把浮点权重和激活值映射到低位宽的整数表示减少内存占用和计算量。以7B模型为例FP16权重约14GBINT8约7GBINT4约3.5GB。手机RAM普遍在8-16GBFP16根本放不下INT8勉强INT4比较现实。但量化会带来精度损失尤其是INT4对模型能力的影响需要仔细评估。4.2 QNN的量化工具链QNN提供了量化工具支持PTQ训练后量化和部分QAT量化感知训练流程。PTQ的流程大致是准备一批校准数据跑一遍模型收集激活值分布然后计算量化参数。校准数据的质量和数量直接影响量化效果。我自己的经验是校准数据最好覆盖实际使用场景的输入分布。比如你做的是对话模型校准数据就应该包含各种长度的对话文本而不是随便拿几百条新闻凑数。另外QNN的量化工具对某些算子如LayerNorm、Softmax的处理比较敏感量化后精度掉得厉害这时候可能需要把这些算子留在CPU上执行。注意量化不是一劳永逸的。同一个模型在不同设备、不同QNN版本上量化效果可能不一样。建议在目标设备上做端到端的精度验证。4.3 混合精度的取舍全INT8量化有时候精度不够全INT4又太激进。混合精度是个折中方案对精度敏感的层用INT8对精度不敏感的层用INT4。QNN支持这种混合精度配置但需要手动指定每层的量化位宽工作量不小。我的建议是先用全INT8跑通看精度是否达标。如果达标再尝试把部分层降到INT4逐步压缩。如果全INT8就不达标那可能需要考虑QAT或者换更小的模型。5. 从模型到部署的完整链路拆解5.1 环境准备与版本对齐这一步看似简单实则是最容易翻车的地方。你需要对齐的版本包括QNN SDK版本、ONNX Runtime版本如果用ORT、设备固件版本、Android NDK版本。高通每个季度会发布新的QNN SDK但设备固件不一定同步更新。如果SDK版本高于设备固件支持的版本可能会报错。我的做法是先确定目标设备查清楚它支持的QNN版本范围然后选择对应的SDK。不要盲目追新。另外QNN SDK的安装和环境变量配置也有讲究官方文档写得比较散建议把QNN_SDK_ROOT、PATH、LD_LIBRARY_PATH这些配好之后写个脚本固化下来。5.2 模型转换与图优化模型转换是第一个硬骨头。以ONNX模型为例你需要用QNN Converter把它转成QNN格式。转换命令大致长这样qnn-onnx-converter \ --input_network model.onnx \ --output_path model.cpp \ --input_dim input_ids 1,128 \ --input_dim attention_mask 1,128 \ --quantization_overrides quant_overrides.json这里有几个关键参数--input_dim指定输入维度大模型的输入通常是动态的但QNN对动态shape支持有限可能需要固定shape--quantization_overrides指定量化配置如果你有自定义的量化参数通过这个文件传入。转换过程中最常见的报错是算子不支持。这时候有两个选择一是修改模型结构用支持的算子替换不支持的算子二是把不支持的算子标记为CPU执行。前者工作量大但性能好后者省事但有性能损失。5.3 运行时集成与内存管理模型转好之后就是集成到Android应用里。QNN提供了C API你需要写JNI层来调用。这里的关键是内存管理NPU的内存和CPU内存是分开的数据在两者之间搬运有开销。QNN提供了共享内存的机制可以减少拷贝。另一个坑是模型加载时间。大模型的QNN模型文件可能几百MB加载到NPU上需要时间。如果每次启动都重新加载用户体验很差。我的做法是做一个常驻服务模型加载一次后续请求复用。5.4 性能调优的实操手段性能调优没有银弹主要靠这几种手段第一调整量化配置找到精度和速度的平衡点第二调整图切分策略把哪些算子放NPU、哪些放CPU第三调整batch size和序列长度找到NPU利用率最高的配置第四用QNN的profiling工具定位瓶颈。我实测下来图切分策略对性能影响最大。如果切得不好数据在NPU和CPU之间来回搬运开销比计算本身还大。原则是尽量让连续的算子在同一设备上执行减少跨设备的数据传输。6. 实测中那些文档不会告诉你的坑6.1 算子兼容性的隐形陷阱官方文档列的支持算子和实际能跑的算子中间有差距。有些算子文档说支持但特定参数组合下会报错。比如Attention算子不同的mask方式、不同的head维度支持情况不一样。我遇到过文档说支持MultiHeadAttention但实际转换时因为head数不是8的倍数而失败。应对策略是尽早做端到端的转换测试不要等到模型都训练完了才发现转不过去。另外保持和QNN SDK版本的同步新版本往往会修复一些算子问题。6.2 内存墙与OOM大模型在NPU上跑内存是硬约束。NPU的专用内存通常比系统RAM小模型权重、激活值、KV Cache都要占内存。7B模型INT8量化后约7GB加上KV Cache和运行时开销很容易OOM。我的经验是第一用INT4量化压缩权重第二限制上下文长度减少KV Cache占用第三及时释放不用的中间张量。QNN提供了一些内存复用机制但需要手动配置。6.3 发热与降频手机跑大模型发热是必然的。NPU满载运行时功耗不低持续跑几分钟后设备会降频保护。降频后推理速度可能掉一半。这个问题在散热好的设备上稍好但物理限制摆在那里。实际产品中需要做热管理策略比如限制单次推理的token数、在温度过高时降级到小模型、或者做请求排队。这些策略需要在应用层实现框架层面帮不了太多。6.4 多线程与并发QNN的上下文不是线程安全的。多个线程同时调用同一个QNN Context会出问题。如果你的应用需要并发推理要么加锁串行化要么创建多个Context。但多个Context会占用更多内存需要权衡。7. 不同场景下的框架选型建议7.1 快速验证场景如果你只是想快速验证高通NPU能不能跑我的模型建议走ONNX Runtime QNN EP这条路。接入成本最低社区资料相对多遇到问题容易找到参考。缺点是性能不是最优但验证阶段够用。7.2 产品级部署场景如果要做产品对性能和稳定性有要求建议直接基于QNN原生API开发。虽然工作量大但能完全控制图切分、内存管理、量化策略性能上限最高。代价是需要投入更多人力做底层适配。7.3 大语言模型专用场景如果是LLM场景llama.cpp的QNN后端值得关注。它针对Transformer结构做了不少优化GGUF格式的量化模型生态也成熟。但要注意它的版本迭代快接口可能变化需要锁定版本。7.4 跨平台兼容场景如果应用需要同时跑在高通、联发科、苹果等多平台NNAPI或ONNX Runtime的抽象层更合适。但要做好心理准备抽象层意味着性能损失高通NPU的特性用不上。8. 我对这条技术路线的个人判断折腾了这段时间我的整体感受是高通NPU跑大模型技术上可行但工程上还有不少路要走。QNN作为官方栈能力是有的但工具链的成熟度、文档的完善度、社区的支持度和服务器端的CUDA生态比还有明显差距。短期内我建议的做法是模型侧做好量化和结构适配框架侧优先考虑ONNX Runtime或llama.cpp的QNN后端部署侧做好热管理和内存管理。不要指望一套配置跑遍所有设备针对主力机型做定向优化是必要的。另外高通的QNN SDK更新频率不低每个版本都可能带来新的算子支持和性能改进。保持关注但不要盲目升级升级前做好回归测试。这个领域变化快今天的最佳实践可能下个月就过时了保持动手测试的习惯比记住任何结论都重要。