三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

让大模型跑在小芯片上的工程挑战记录:部署前别漏掉这些配置

让大模型跑在小芯片上的工程挑战记录:部署前别漏掉这些配置

让大模型跑在小芯片上的工程挑战记录:部署前别漏掉这些配置

在 8GB 甚至 4GB 内存的端侧板卡上部署 3B / 0.5B 级别的端侧小语言模型(SLM),极度考验底层工程治理。许多项目在开发阶段运行良好,一放到生产环境,设备运行几天就莫名重启,或者在并发请求到来时触发 Kernel OOM 杀进程。

造成这些故障的原因,往往不是模型本身出了问题,而是没有做好生产部署拓扑划分,忽略了系统级资源隔离与驱动配置锁死。

flowchart TD A[边缘系统 Linux Kernel & Bootargs] --> B[ZRAM / Memory Swap 彻底禁用] A --> C[cgroups v2 硬性限制隔离区] C --> D[Systemd 进程防护:SLM Runtime] C --> E[业务逻辑 CPU / 内存保护区] D --> F[NPU/GPU 驱动句柄与 DMA-BUF 缓存池] F --> G{运行时内存 & 句柄监控} G -- 超过 85% 预警阈值 -- H[拒绝 Incoming Token,触发主动降级] G -- 触发 OOM Killer -- I[Systemd 自动重启并 Dump Trace]

1. 为什么小芯片部署 SLM 极其容易触发 OOM

小芯片(如 RK3588、Jetson Orin Nano)的 DRAM 内存是系统 CPU 与 GPU/NPU 共享的统一内存架构(UMA)。

当部署一个 Q4_K 量化版的 3B 参数模型时,模型权重本身要占用大约 1.8GB 内存。但这仅仅是静态开销。一旦模型启动推理,KV Cache 随着上下文长度增长(如从 512 token 扩展到 2048 token)会急剧膨胀。如果再叠加 NPU 驱动申请的 DMA-BUF 连续物理内存块,总内存占用会迅速逼近 3.5GB 临界线。

当系统内存耗尽时,默认的 Linux 内核开始拼命换页。如果系统开启了 Swap 或 ZRAM,CPU 会暴涨到 100% 忙于解压缩内存页,导致整个系统卡死;如果关闭了 Swap 且没有对系统关键进程设定保护,Linux 内核的oom-killer就会根据 score 随机杀死进程,往往直接将 SLM 推理守护进程挂掉。

2. 内核参数与硬件驱动环境治理

在部署 SLM 推理服务前,必须对 Linux 内核与驱动层进行彻底清理,排除潜在的隐患。

2.1 彻底关闭 Swap 与 Swappiness 调优

端侧板卡的 Flash 读写寿命有限,且 Swap 带来的磁盘 I/O 延迟无法满足大模型实时 Token 输出。必须在/etc/sysctl.conf中禁用 Swappiness:

# 查看当前内存与 Swap 使用状态 free -h cgget -r memory.current /system.slice/slm_inference.service # 临时与永久关闭 Swap sysctl -w vm.swappiness=0 sysctl -w vm.overcommit_memory=2 sysctl -w vm.overcommit_ratio=80 # 写入配置文件确保重启生效 cat <<EOF >> /etc/sysctl.d/99-slm-hardening.conf vm.swappiness=0 vm.overcommit_memory=2 vm.overcommit_ratio=80 EOF sysctl --system

2.2 NPU/GPU 内存分配上限控制(以 Rockchip RK3588 为例)

针对 RK3588 等支持 RKNPU 的芯片,驱动默认可能没有限制单个 Context 申请的 CMA(Contiguous Memory Allocator)内存大小。需检查/proc/atf//sys/kernel/debug/rknpu/节点:

# 检查 CMA 内存池占用 cat /proc/meminfo | grep Cma # 在 /boot/armbianEnv.txt 或 uEnv.txt 中硬编码 cma 区域大小,防止被驱动过度占用 # 限制 CMA 最大为 2048M bootargs=root=UUID=... quiet cma=2048M

3. Systemd 结合 cgroups v2 的生产级资源隔离配置

在生产环境中,绝不能直接用 nohup 启动 Python 或 C++ 的 SLM 服务。必须通过 Systemd 配合 cgroups v2 严格划定内存与 CPU 资源边界,确保 SLM 进程即便内存溢出,也不会拖垮系统关键网络通信与监控服务。

创建/etc/systemd/system/slm_inference.service配置文件:

[Unit] Description=Small Language Model Inference Engine After=network-online.target rknpu.service Wants=network-online.target [Service] Type=simple User=root WorkingDirectory=/opt/slm_engine ExecStart=/opt/slm_engine/bin/llama-cli \ -m /opt/slm_engine/models/qwen2.5-0.5b-instruct-q4_k_m.gguf \ -c 2048 \ -t 4 \ --host 0.0.0.0 --port 8080 # 资源限制与 cgroups v2 防护收口 CPUAccounting=true MemoryAccounting=true # 设定硬内存上限为 2.8 GB(针对 4GB 总内存板卡) MemoryHigh=2600M MemoryMax=2800M # 发生 OOM 时优先杀死本服务,保护系统 Shell 与核心 Daemon OOMScoreAdjust=500 # 故障重启策略:5秒内重启,最多尝试 3 次防止无限崩溃 Restart=on-failure RestartSec=5s StartLimitIntervalSec=60s StartLimitBurst=3 # 绑定核心运行在 4 个大核上(针对 RK3588 4小核+4大核架构) CPUAffinity=4 5 6 7 [Install] WantedBy=multi-user.target

重载 Systemd 并验证 cgroups 绑定情况:

systemctl daemon-reload systemctl start slm_inference.service systemctl status slm_inference.service # 查看是否精准挂载到 cgroups v2 节点 systemd-cgls /system.slice/slm_inference.service

4. 运行时拓扑巡检与异常自动降级

治理环境配置后,还需要配套运行时自动化巡检脚本。脚本一旦捕获到连续内存逼近MemoryHigh阀值,立即通过 API 降低最大生成 Token 数或清空历史上下文。

#!/usr/bin/bash # monitor_slm_health.sh SERVICE_NAME="slm_inference.service" THRESHOLD_MB=2500 LOG_OOM=$(dmesg -T | grep -iE "oom-killer|out of memory" | tail -n 5) if [ -n "$LOG_OOM" ]; then echo "[CRITICAL ALERT] OOM Detected in Kernel Logs!" echo "$LOG_OOM" # 可在此处触发告警推送 fi # 获取服务当前物理内存 (RSS) MEM_BYTES=$(systemctl show $SERVICE_NAME --property=MemoryCurrent | cut -d= -f2) if [ "$MEM_BYTES" = "[not set]" ] || [ -z "$MEM_BYTES" ]; then echo "[ERROR] Cannot fetch memory metrics." exit 1 fi MEM_MB=$((MEM_BYTES / 1024 / 1024)) echo "[INFO] Current SLM RSS Memory: ${MEM_MB} MB" if [ $MEM_MB -gt $THRESHOLD_MB ]; then echo "[WARNING] Memory usage ${MEM_MB}MB exceeded threshold ${THRESHOLD_MB}MB. Invoking Context Truncation API..." # 调 API 强制截断长上下文,释放 KV Cache 空间 curl -s -X POST http://127.0.0.1:8080/api/v1/context/trim -H "Content-Type: application/json" -d '{"keep_recent": 512}' fi

通过这套内核级 Swappiness 封锁、Systemd cgroups v2 硬性挂载以及内存限流降级机制,能够大幅提升端侧小芯片部署大模型后的系统稳健性,保障设备连续跑版不宕机。

← 返回列表