最近半年,我参与了一个项目,把原来跑在云端的AI功能迁移到了端侧设备上。

整个过程踩了不少坑,也积累了一些经验。这篇文章,我想分享一下这次端侧AI迁移的实战经历,包括为什么要迁移、怎么选方案、遇到了什么问题、最后是怎么解决的。

为什么要做端侧AI迁移

先说说为什么要做这次迁移。

我们的旧系统是一个云端AI方案,设备采集数据,传到云端服务器,服务器跑AI模型,把结果返回给设备。这个方案用了两年,整体还算稳定,但随着业务发展,问题越来越多。

第一个问题是延迟。数据从设备传到云端,再从云端返回结果,网络延迟至少有几百毫秒。在一些对实时性要求高的场景,比如实时检测、实时交互,这个延迟是不可接受的。

第二个问题是网络依赖。设备必须联网才能使用AI功能。在网络不好的地方,或者没有网络的环境下,功能就用不了。我们的很多客户是在工厂、工地这种网络环境差的地方,这个问题很突出。

第三个问题是成本。云端服务器的成本很高,GPU服务器很贵,而且随着用户量增长,成本线性增长。还有带宽成本,大量数据传输也是一笔不小的开支。

第四个问题是隐私。有些客户的数据比较敏感,不愿意把数据传到云端。虽然我们做了加密,但客户还是希望数据能在本地处理,不出设备。

基于这些原因,公司决定把AI功能迁移到端侧,让模型直接在设备上运行。这样既可以降低延迟,又可以摆脱网络依赖,还能降低成本和保护隐私。

方案选型

确定了要做端侧AI之后,接下来就是方案选型。

端侧AI的方案有很多,我们主要考虑了以下几个维度:

第一个维度是硬件平台。我们的设备用的是ARM架构的嵌入式处理器,性能有限。需要选一个能在这种硬件上高效运行的推理框架。

第二个维度是模型格式。我们原来的模型是PyTorch训练的,需要转换成端侧能运行的格式。不同的框架支持的模型格式不一样,需要考虑转换的便利性和损失。

第三个维度是性能。模型在端侧运行的速度、内存占用、功耗,都是需要考虑的。我们的目标是,模型推理时间不超过100毫秒,内存占用不超过500MB。

第四个维度是生态和社区。框架的文档是否完善,社区是否活跃,遇到问题能不能找到解决方案,这些都很重要。

我们调研了几个主流的端侧推理框架:

TensorFlow Lite:Google出的,生态成熟,支持多种硬件,但主要支持TensorFlow模型,PyTorch模型需要先转成ONNX再转TFLite,比较麻烦。

ONNX Runtime:微软出的,支持ONNX格式,跨平台,性能不错,支持多种硬件加速。

NCNN:腾讯出的,针对移动端优化,性能很好,支持多种神经网络,但文档相对少一些。

MNN:阿里出的,轻量级,性能不错,支持多种后端,但社区相对小一些。

Core ML:苹果的,只能在iOS/macOS上用,我们的设备是安卓/Linux,不适用。

经过评估,我们最终选择了ONNX Runtime。原因是:它支持ONNX格式,PyTorch模型可以直接转ONNX,转换方便;跨平台,支持我们的ARM Linux设备;性能不错,支持NNAPI、OpenCL等硬件加速;文档和社区都比较好。

模型转换和优化

选好框架之后,第一步是把PyTorch模型转换成ONNX格式。

这个过程看起来简单,但实际踩了不少坑。

第一个坑是,模型里有一些动态的操作,比如动态shape、条件分支,这些在导出ONNX的时候会出问题。我们需要把这些动态操作改成静态的,或者用ONNX支持的方式重写。

第二个坑是,有些PyTorch的算子,ONNX不支持,或者支持得不好。比如某些特殊的归一化层、某些激活函数。遇到这种情况,要么用其他算子代替,要么自定义算子。

第三个坑是,转换之后的模型精度有损失。虽然理论上ONNX转换是无损的,但实际上因为算子实现的差异,数值会有微小的差异。对于我们的模型来说,这个差异在可接受范围内,但有些对精度要求高的模型,可能需要做量化感知训练。

模型转成ONNX之后,还需要做优化。ONNX Runtime提供了一些优化工具,比如算子融合、常量折叠、死代码消除等。这些优化可以减少模型的计算量,提升推理速度。

我们还做了量化。把模型从FP32量化到INT8,模型体积减少了75%,推理速度提升了2-3倍,内存占用也大幅降低。量化的精度损失在我们的场景下是可以接受的。

不过,量化也不是随便做的。需要用有代表性的数据做校准,确保量化后的模型精度不会下降太多。我们一开始随便选了一些数据做校准,结果精度下降很明显。后来用了真实场景的数据做校准,精度就好了很多。

性能优化

模型跑起来之后,性能还不达标。推理时间大概是300毫秒,我们的目标是100毫秒以内。于是开始做性能优化。

第一个优化是硬件加速。ONNX Runtime支持多种执行提供者(Execution Provider),比如CPU、NNAPI、OpenCL、Vulkan等。我们的设备有GPU,于是尝试用OpenCL后端。开启之后,推理速度提升了约40%。

但OpenCL也有问题。首先是模型的某些算子不支持OpenCL,会回退到CPU,导致数据在CPU和GPU之间频繁拷贝,反而变慢。我们需要把这些不支持的算子找出来,要么改成支持的算子,要么做一些调整。

第二个优化是模型结构优化。我们分析了模型的推理时间分布,发现有几个层占了大部分时间。于是我们对这几个层做了优化,比如用更高效的算子代替、减少通道数、调整卷积核大小等。这些优化让推理速度又提升了30%。

第三个优化是内存优化。端侧设备的内存有限,我们需要尽量减少内存占用。我们用了内存复用技术,让不同层的内存可以复用,减少了峰值内存占用。还做了模型的内存规划,提前分配好内存,避免运行时动态分配。

第四个优化是预处理和后处理优化。AI推理不只是模型本身,还包括图像预处理(缩放、归一化等)和结果后处理。我们发现预处理和后处理也占了不少时间,于是用了更高效的图像处理库,还把一些处理放到了GPU上,又省了一些时间。

经过这些优化,推理时间从300毫秒降到了80毫秒,达到了目标。内存占用也从800MB降到了300MB。

系统集成

模型性能达标之后,接下来是系统集成。

我们的旧系统是云端架构,设备端只负责采集数据和显示结果。现在要把AI功能放到端侧,需要重新设计系统架构。

新的架构是这样的:设备端负责数据采集、AI推理、结果展示。云端负责模型管理、数据统计、远程升级。设备端和云端之间通过轻量级的协议通信,只传输必要的信息,不传输原始数据。

系统集成中遇到的第一个问题是,AI推理和其他功能的资源竞争。设备的CPU和内存是有限的,AI推理占用了很多资源,导致其他功能变慢。我们的解决方案是,给AI推理设置资源限制,比如限制CPU核心数、限制内存使用。还做了任务调度,在用户交互的时候降低AI推理的优先级,保证用户体验。

第二个问题是,模型的热更新。AI模型需要经常更新,如果每次更新都要升级整个应用,很麻烦。我们做了一个模型管理模块,可以从云端下载新模型,热加载到运行时中,不需要重启应用。还做了版本管理和回滚机制,如果新模型有问题,可以快速回滚到旧版本。

第三个问题是,异常处理。端侧环境复杂,可能会出现各种异常,比如模型加载失败、推理超时、内存不足等。我们做了完善的异常处理机制,每种异常都有对应的处理策略,确保系统不会崩溃,而且能自动恢复。

第四个问题是,日志和监控。端侧设备出了问题,不像云端那样可以直接登录查看。我们做了远程日志收集功能,设备端的日志可以上传到云端,方便排查问题。还做了性能监控,实时监控推理时间、内存占用、CPU使用率等指标。

测试和验证

系统集成完成之后,就是测试和验证。

端侧AI的测试比云端复杂,因为需要在真实设备上测试,而且设备的硬件环境多样。

我们做了几个层面的测试:

第一个是精度测试。在同样的测试集上,对比端侧模型和云端模型的输出,确保精度差异在可接受范围内。我们还做了长期稳定性测试,确保模型在长时间运行下不会出现精度漂移。

第二个是性能测试。在不同的设备型号上测试推理时间、内存占用、功耗,确保都能达到要求。还做了压力测试,连续运行几个小时,看系统是否稳定。

第三个是兼容性测试。我们的设备有多个型号,硬件配置不一样,需要确保在所有设备上都能正常运行。还测试了不同的系统版本、不同的运行环境。

第四个是场景测试。在真实的使用场景下测试,比如工厂、工地、户外等,确保在各种环境下都能正常工作。

测试过程中发现了不少问题,比如某些设备上GPU加速不工作、某些场景下模型精度下降、长时间运行后内存泄漏等。这些问题都一一修复了。

迁移后的效果

经过半年的努力,端侧AI迁移终于完成了。迁移之后的效果,比我们预期的还要好。

第一个效果是延迟大幅降低。从原来的几百毫秒降到了80毫秒,用户体验提升非常明显。实时检测和交互的场景,现在都能流畅使用了。

第二个效果是摆脱了网络依赖。设备在没有网络的环境下也能正常使用AI功能,这对于我们的很多客户来说是刚需。

第三个效果是成本降低。云端服务器的成本减少了70%,带宽成本也大幅下降。虽然端侧设备的成本略有增加,但整体TCO(总拥有成本)还是降低了。

第四个效果是客户满意度提升。隐私问题解决了,延迟问题解决了,网络问题解决了,客户的反馈非常好。

当然,也有一些挑战。比如端侧设备的性能有限,复杂的模型跑不起来,需要在模型精度和性能之间做权衡。还有模型更新的管理,需要确保所有设备都能及时更新到最新模型。

一些经验总结

最后,总结一些端侧AI迁移的经验。

第一,不要盲目追求端侧。不是所有AI功能都适合放到端侧。如果模型很复杂,对精度要求很高,端侧设备跑不起来,那还是放云端比较好。端侧适合那些对延迟敏感、对隐私要求高、网络环境差的场景。

第二,选型很重要。框架、硬件、模型格式的选择,会直接影响后续的开发效率和最终效果。在选型阶段多花时间,比后期返工要好得多。

第三,性能优化是持久战。端侧的性能优化不是一次就能搞定的,需要不断地分析、优化、测试。而且不同的设备性能差异很大,需要针对不同设备做适配。

第四,重视系统集成。AI模型只是系统的一部分,如何把模型集成到整个系统中,如何处理资源竞争、异常、更新等问题,同样重要。

第五,测试要充分。端侧环境复杂,一定要在真实设备上、真实场景下做充分的测试。很多问题只有在特定的设备和场景下才会出现。

端侧AI是未来的趋势,随着端侧硬件性能的提升和模型优化技术的进步,越来越多的AI功能会从云端迁移到端侧。希望我们的经验能帮到正在做类似事情的朋友。