Orange Pi AI Pro · 昇腾 310B4 · CANN 8.5.1 · llama.cpp
整整一天,隧道通了,编译过了,模型就位了,但 NPU 推理本身一次都没成功跑完过。板子三次卡死,NPU 内存泄漏,只能靠重启解决。
这是踩坑记录,不是成功教程。
第一章
板子在办公室,我在远端——先把手伸进去
Orange Pi AI Pro 放在办公室角落,接着网线,不在身边。要操作它,第一步不是跑模型,而是想办法远程连进去。
这块板子没有公网 IP,但有 Cloudflare Zero Trust 隧道可以用。挑了个闲置域名 bopomofo.top,建了一个叫 orangepi 的隧道,把 SSH 暴露到 ssh.bopomofo.top。
连通性检测跑完,region2 的 TCP 有一条 FAIL,cloudflared 自动降级走 QUIC——不影响用,SSH 连上了。
小插曲
当时没意识到的问题:cloudflared 只是在前台手动跑着,一旦断连或板子重启,隧道就没了。这个埋雷埋了一整天。
SSH 一进去,马上踩坑。grep、uname、dirname、sed——这些连 Linux 用户都不会多想的命令,全部 command not found。
排查了一会儿才明白:通过 CF 隧道进来的 SSH session,PATH 是空的。系统二进制路径根本没有被加进去。以后每次登录,都得先手动 export 一遍:
不是什么大问题,但它会在之后的每一步操作里默默埋坑。
第二章
编译:通了——但我开始怀疑它有没有意义
目标是用 llama.cpp 的 CANN 后端把语言模型跑在 NPU 上。310B4 是华为昇腾芯片,它的 AI 框架叫 CANN,不是 CUDA。llama.cpp 官方支持 CANN 后端,但需要手动编译,并且踩坑从编译阶段就开始了。
按照官方文档配置好 cmake,开始构建。跑了一会儿,报错停了下来:
编译错误
Q4_0 量化格式的自定义内核需要 half → int4b_t 的类型转换,310B4 的核心架构 DAV-M200 没有实现这个操作。硬件级别的限制。
这里卡了一段时间。搜了社区,没找到针对 310B4 的现成 patch。然后出现了第一个真正的纠结:
纠结时刻 #1
Q4_0 内核编不过,怎么办?
绕过去
加 -DGGML_CANN_CUSTOM_KERNELS=OFF,禁用自定义内核,编译通过。快,今天能看到结果。
找根本解法
找华为 ATC 工具链,把模型转成 .om 格式,这才是 310B4 的设计用途。但工作量大,可能要几天。
选了绕过去。加了一个 cmake flag,编译顺利跑完,产出了完整的 llama.cpp 套件——llama-cli、llama-server、llama-bench……看起来一切就绪。
事后复盘
Q4_0 是最普遍的量化格式。把承载这组格式的内核全部关掉,NPU 能接的算子已经残缺了。这个绕路方案,从一开始就注定了 NPU 利用率会很低,只是当时没意识到。
还有一个小插曲:source CANN 环境变量脚本时,终端刷了几十行报错:
一开始以为环境没配成功,慌了一下。后来发现 LD_LIBRARY_PATH 其实已经设进去了——set_env.sh 的那些报错是 PATH 为空导致的副作用,不致命。先 export PATH 再 source,报错消失。这个坑的解法其实在第一章就埋好了,只是没及时用上。
第三章
板子第一次卡死
编译完,模型也有了——qwen2.5-7b-instruct-q4_k_m.gguf,Qwen2.5-7B Q4_K_M,放在 /root/llama.cpp/ 下。万事俱备,跑推理:
命令发出去,终端在等待。等了十几秒,没有输出。再等,还是没有。然后——
SSH 断了。
不是超时,是板子卡死了。llama-cli 开始把 7B 模型往 NPU 显存加载,这个过程把 CPU 和内存同时打满,整块板子失去响应。局域网直连 SSH 断,CF 隧道 SSH 也断。
只剩一条路:从 Pi5 通过 CF 隧道发一个杀进程的命令,赌 tunneld 还活着:
赌赢了,进程被杀。板子缓过来,SSH 重新能连。
整个过程没有看到任何推理输出,也不知道 NPU 有没有真的接到任务。唯一能确定的是:板子被搞崩了。
第四章
NPU 的"残影":内存不释放,Alarm 状态
重新连进去,第一件事是看 NPU 状态:
| NPU Name | Health | Power(W) Temp(C) Hugepages
| Chip Device| Bus-Id | AICore(%) Memory-Usage(MB)
|============|============|==================================|
| 0 310B4 | Alarm | 0.0 52 |
| 0 0 | NA | 0 10658 / 15610 |
进程已死,NPU 却还占着 10658MB——超过总显存的三分之二。ps 里看不到任何模型推理进程,但 NPU 死活不肯释放这块内存,Health 也挂着 Alarm。
这时想到,应该有办法软件重置 NPU。试了:
报错
npu-smi 根本没有 reset 子命令。支持的只有 info、set、clear、upgrade。
纠结时刻 #2
NPU 内存泄漏,无法软件解决,怎么办?
找驱动层方案
尝试 rmmod / insmod NPU 驱动,重新挂载。风险高,可能让系统进入更糟的状态。
重启板子
最稳妥,也是唯一确定有效的方法。内存完全清零,状态归位。代价是要等。
选择等重启——但板子在办公室,已经快晚上了。
第五章
"整整一天了,毛进展都没"
这是真实说过的一句话。
白天折腾了隧道、SSH 的 PATH、CANN 的环境变量、Q4_0 内核报错、绕路编译、第一次跑推理卡死……每一步都在解决上一步暴露出来的问题,解决完又发现新的坑。进度感很强,但实际上往后退一步看:NPU 推理,一次都没真正跑通过。
最讽刺的是当时 npu-smi info 显示的状态:
Health: AlarmNPU 内存: 10658/15610 MBAICore: 0%llama.cpp: 编译完成模型文件: 就位cloudflared: 手动跑着
万事俱备,但 NPU 已经是一个半残废的状态,而且唯一的修复方法是重启,而重启意味着明天再说。
好不容易折衷再折衷,然后现在回家了,你跟我说连 SSH 进去都不行了。
是的。这就是这一天的结局:隧道断了,NPU 卡着,板子在办公室,人在回家的路上。
第六章
回头看:哪里走错了,下次怎么做
错误一:前台跑推理
直接 SSH 前台执行 llama-cli,模型加载时板子卡死,SSH 直接断。正确做法是用 nohup 后台跑,把日志写到文件,另开窗口 tail -f 监控,板子卡了还能从别的 SSH 窗口处理。
错误二:没验证 NPU 真的在用
在尝试推理之前,其实应该先确认 -DGGML_CANN_CUSTOM_KERNELS=OFF 的代价——运行一个最小模型,盯着 watch npu-smi info 看 AICore% 有没有变化。如果始终是 0%,说明 NPU 根本没接任务,后面所有推理尝试都是白费。
错误三:没装 systemd 服务
cloudflared 手动跑,板子一重启隧道就没了。应该第一天就装好 systemd 服务,之后所有连接才是可靠的。
下次重启后的正确操作顺序
Step 1 — 确认 NPU 干净
Step 2 — 装 cloudflared 服务(只需一次)
Step 3 — 后台跑推理 + 同步监控
如果推理过程中 AICore% 一直是 0,就可以断定:-DGGML_CANN_CUSTOM_KERNELS=OFF 绕路方案行不通,需要换路线——找社区里针对 310B4 维护的 llama.cpp fork,或者走华为官方的 ATC + .om 格式转换流程。
那就是另一天的故事了。
第七章 · 终章
真相:这条路根本不存在
第二天,重启板子,NPU 内存清零,换了 Q8_0 格式的模型,29 层全部卸进 NPU 显存(7165MB 成功加载)——然后推理一启动就崩:
最终错误
不是量化格式问题,不是编译参数问题——310B 这颗芯片在 llama.cpp 的 CANN 后端里,矩阵乘法计算根本没有实现。
去查了 vLLM-Ascend 的支持矩阵,所有支持的硬件清一色是 A2/A3——也就是昇腾 910 系列,服务器级大卡。310B4 根本不在列。整个主流开源 LLM 推理生态(llama.cpp、vLLM、MindSpore-LLM 社区版)都是围绕 910 系列建的。
最终结论
310B4 是边缘推理芯片,设计目标是跑预编译的 .om 格式模型——YOLO、分类、OCR 这类固定计算图。它能跑 LLM,但唯一成熟的路径是用华为 ATC 工具把模型转成 .om 格式,完全绕开 Python/GGUF 生态。
不是没人试过,而是生态就没往这个方向走。
两天,六个坑,最后发现撞的不是墙,是悬崖。模型加载进了 NPU 内存,距离真正推理只差一步——但那一步,需要整个生态系统补齐才能迈出去。
310B4 跑 YOLO 目标检测是完全成熟的,NPU 在那个场景里能发挥真实价值。LLM 这条路,至少在 2026 年中,还是死路。
结案 · NPU LLM 推理:生态不支持
Orange Pi AI Pro · 昇腾 310B4 · CANN 8.5.1 · llama.cpp
整整一天,隧道通了,编译过了,模型就位了,但 NPU 推理本身一次都没成功跑完过。板子三次卡死,NPU 内存泄漏,只能靠重启解决。
这是踩坑记录,不是成功教程。
第一章
板子在办公室,我在远端——先把手伸进去
Orange Pi AI Pro 放在办公室角落,接着网线,不在身边。要操作它,第一步不是跑模型,而是想办法远程连进去。
这块板子没有公网 IP,但有 Cloudflare Zero Trust 隧道可以用。挑了个闲置域名
bopomofo.top,建了一个叫orangepi的隧道,把 SSH 暴露到ssh.bopomofo.top。连通性检测跑完,region2 的 TCP 有一条 FAIL,cloudflared 自动降级走 QUIC——不影响用,SSH 连上了。
小插曲
当时没意识到的问题:cloudflared 只是在前台手动跑着,一旦断连或板子重启,隧道就没了。这个埋雷埋了一整天。
SSH 一进去,马上踩坑。
grep、uname、dirname、sed——这些连 Linux 用户都不会多想的命令,全部command not found。排查了一会儿才明白:通过 CF 隧道进来的 SSH session,PATH 是空的。系统二进制路径根本没有被加进去。以后每次登录,都得先手动 export 一遍:
不是什么大问题,但它会在之后的每一步操作里默默埋坑。
第二章
编译:通了——但我开始怀疑它有没有意义
目标是用 llama.cpp 的 CANN 后端把语言模型跑在 NPU 上。310B4 是华为昇腾芯片,它的 AI 框架叫 CANN,不是 CUDA。llama.cpp 官方支持 CANN 后端,但需要手动编译,并且踩坑从编译阶段就开始了。
按照官方文档配置好 cmake,开始构建。跑了一会儿,报错停了下来:
编译错误
Q4_0 量化格式的自定义内核需要 half → int4b_t 的类型转换,310B4 的核心架构 DAV-M200 没有实现这个操作。硬件级别的限制。
这里卡了一段时间。搜了社区,没找到针对 310B4 的现成 patch。然后出现了第一个真正的纠结:
纠结时刻 #1
Q4_0 内核编不过,怎么办?
绕过去
加
-DGGML_CANN_CUSTOM_KERNELS=OFF,禁用自定义内核,编译通过。快,今天能看到结果。找根本解法
找华为 ATC 工具链,把模型转成 .om 格式,这才是 310B4 的设计用途。但工作量大,可能要几天。
选了绕过去。加了一个 cmake flag,编译顺利跑完,产出了完整的 llama.cpp 套件——
llama-cli、llama-server、llama-bench……看起来一切就绪。事后复盘
Q4_0 是最普遍的量化格式。把承载这组格式的内核全部关掉,NPU 能接的算子已经残缺了。这个绕路方案,从一开始就注定了 NPU 利用率会很低,只是当时没意识到。
还有一个小插曲:source CANN 环境变量脚本时,终端刷了几十行报错:
一开始以为环境没配成功,慌了一下。后来发现
LD_LIBRARY_PATH其实已经设进去了——set_env.sh 的那些报错是 PATH 为空导致的副作用,不致命。先 export PATH 再 source,报错消失。这个坑的解法其实在第一章就埋好了,只是没及时用上。第三章
板子第一次卡死
编译完,模型也有了——
qwen2.5-7b-instruct-q4_k_m.gguf,Qwen2.5-7B Q4_K_M,放在/root/llama.cpp/下。万事俱备,跑推理:命令发出去,终端在等待。等了十几秒,没有输出。再等,还是没有。然后——
SSH 断了。
不是超时,是板子卡死了。llama-cli 开始把 7B 模型往 NPU 显存加载,这个过程把 CPU 和内存同时打满,整块板子失去响应。局域网直连 SSH 断,CF 隧道 SSH 也断。
只剩一条路:从 Pi5 通过 CF 隧道发一个杀进程的命令,赌 tunneld 还活着:
赌赢了,进程被杀。板子缓过来,SSH 重新能连。
第四章
NPU 的"残影":内存不释放,Alarm 状态
重新连进去,第一件事是看 NPU 状态:
| NPU Name | Health | Power(W) Temp(C) Hugepages
| Chip Device| Bus-Id | AICore(%) Memory-Usage(MB)
|============|============|==================================|
| 0 310B4 | Alarm | 0.0 52 |
| 0 0 | NA | 0 10658 / 15610 |
进程已死,NPU 却还占着 10658MB——超过总显存的三分之二。
ps里看不到任何模型推理进程,但 NPU 死活不肯释放这块内存,Health 也挂着 Alarm。这时想到,应该有办法软件重置 NPU。试了:
报错
npu-smi 根本没有 reset 子命令。支持的只有 info、set、clear、upgrade。
纠结时刻 #2
NPU 内存泄漏,无法软件解决,怎么办?
找驱动层方案
尝试 rmmod / insmod NPU 驱动,重新挂载。风险高,可能让系统进入更糟的状态。
重启板子
最稳妥,也是唯一确定有效的方法。内存完全清零,状态归位。代价是要等。
选择等重启——但板子在办公室,已经快晚上了。
第五章
"整整一天了,毛进展都没"
这是真实说过的一句话。
白天折腾了隧道、SSH 的 PATH、CANN 的环境变量、Q4_0 内核报错、绕路编译、第一次跑推理卡死……每一步都在解决上一步暴露出来的问题,解决完又发现新的坑。进度感很强,但实际上往后退一步看:NPU 推理,一次都没真正跑通过。
最讽刺的是当时
npu-smi info显示的状态:Health: AlarmNPU 内存: 10658/15610 MBAICore: 0%llama.cpp: 编译完成模型文件: 就位cloudflared: 手动跑着
万事俱备,但 NPU 已经是一个半残废的状态,而且唯一的修复方法是重启,而重启意味着明天再说。
是的。这就是这一天的结局:隧道断了,NPU 卡着,板子在办公室,人在回家的路上。
第六章
回头看:哪里走错了,下次怎么做
错误一:前台跑推理
直接 SSH 前台执行
llama-cli,模型加载时板子卡死,SSH 直接断。正确做法是用nohup后台跑,把日志写到文件,另开窗口tail -f监控,板子卡了还能从别的 SSH 窗口处理。错误二:没验证 NPU 真的在用
在尝试推理之前,其实应该先确认
-DGGML_CANN_CUSTOM_KERNELS=OFF的代价——运行一个最小模型,盯着watch npu-smi info看 AICore% 有没有变化。如果始终是 0%,说明 NPU 根本没接任务,后面所有推理尝试都是白费。错误三:没装 systemd 服务
cloudflared 手动跑,板子一重启隧道就没了。应该第一天就装好 systemd 服务,之后所有连接才是可靠的。
下次重启后的正确操作顺序
Step 1 — 确认 NPU 干净
Step 2 — 装 cloudflared 服务(只需一次)
Step 3 — 后台跑推理 + 同步监控
如果推理过程中 AICore% 一直是 0,就可以断定:
-DGGML_CANN_CUSTOM_KERNELS=OFF绕路方案行不通,需要换路线——找社区里针对 310B4 维护的 llama.cpp fork,或者走华为官方的 ATC + .om 格式转换流程。那就是另一天的故事了。
第七章 · 终章
真相:这条路根本不存在
第二天,重启板子,NPU 内存清零,换了 Q8_0 格式的模型,29 层全部卸进 NPU 显存(7165MB 成功加载)——然后推理一启动就崩:
最终错误
不是量化格式问题,不是编译参数问题——310B 这颗芯片在 llama.cpp 的 CANN 后端里,矩阵乘法计算根本没有实现。
去查了 vLLM-Ascend 的支持矩阵,所有支持的硬件清一色是 A2/A3——也就是昇腾 910 系列,服务器级大卡。310B4 根本不在列。整个主流开源 LLM 推理生态(llama.cpp、vLLM、MindSpore-LLM 社区版)都是围绕 910 系列建的。
最终结论
310B4 是边缘推理芯片,设计目标是跑预编译的 .om 格式模型——YOLO、分类、OCR 这类固定计算图。它能跑 LLM,但唯一成熟的路径是用华为 ATC 工具把模型转成 .om 格式,完全绕开 Python/GGUF 生态。
不是没人试过,而是生态就没往这个方向走。
两天,六个坑,最后发现撞的不是墙,是悬崖。模型加载进了 NPU 内存,距离真正推理只差一步——但那一步,需要整个生态系统补齐才能迈出去。
310B4 跑 YOLO 目标检测是完全成熟的,NPU 在那个场景里能发挥真实价值。LLM 这条路,至少在 2026 年中,还是死路。
结案 · NPU LLM 推理:生态不支持