在嵌入式与边缘AI芯片上部署微调后的大模型:一场内存与速度的极限拉扯
上周深夜,团队里一位工程师在群里发了一张图:一块巴掌大的开发板,连着串口终端,屏幕上赫然一行Killed——那是 Linux 的 OOM Killer 出手干掉了我们刚部署上去的 3B 参数量微调模型。旁边跟着一句留言:“模型在 PC 上跑得好好的,一上板子就崩了。” 这个场景,恐怕很多尝试在嵌入式或边缘设备部署大模型的同行都遇到过。今天我们就来聊聊,如何让微调后的大模型真正在资源受限的芯片上“跑起来”,而不只是“编译通过”。
从“能跑”到“能用”的鸿沟
很多人以为,模型微调完成后,导出 ONNX 或 TorchScript,扔进芯片厂商提供的推理框架里,编译出二进制文件,任务就结束了。实际上,那只是万里长征第一步。嵌入式环境和云端服务器的差异,远比想象中巨大。内存带宽限制、缓存大小、非统一内存架构(NUMA)、异构计算单元调度……这些在服务器上可以忽略的问题,在嵌入式场景下个个都能要命。
以我们遇到的那个 OOM 问题为例。在 x86 服务器上,内存是“充足资源”,动态分配、内存碎片都不是大问题。但在嵌入式设备上,内存是“稀缺资源”。那个 3B 模型在推理时峰值内存达到 4GB,而板子总共只有 4GB RAM,还要分给操作系统和其他服务。不崩才怪。
模型瘦身:不只是量化那么简单
说到嵌入式部署,大家第一反应是量化。没错,INT8 量化能把模型体积砍半,甚至更多。但很多人直接拿 PyTorch 的quantize_per_tensor搞一遍就完事,结果发现精度掉得亲妈都不认识,或者推理速度根本没提升。
这里踩过坑:量化一定要和芯片的硬件特性结合。比如某些边缘 AI 芯片只对卷积层有 INT8 加速,全连接层还是 FP32 跑。这时候全模型量化反而可能因为频繁做数据类型转换拖慢速度。我们的做法是,用芯片厂商提供的 profiling 工具跑一遍,看哪些算子占了大部分时间,针对性地对这些算子做量化。
还有更狠的:结构化剪枝。不是随便剪掉一些权重小的连接,而是按照芯片的计算单元特点来剪。比如某款芯片的 NPU 是 128 通道并行,那我们剪枝时就保持通道数是 128 的倍数,避免硬件计算单元闲置。
# 一个实际部署时的权重转换片段defadapt_weights_for_hardware(weight,hardware_block_size=128):# 获取原始形状out_channels,in_channels=weight.shape[<