昇腾 910B 部署大模型:从认卡到 40 人共用一台机器的实录
这台昇腾 910B2(64GB HBM)拿到手时,我习惯性地敲了 nvidia-smi——屏幕空了。机器里一块 NVIDIA 卡都没有,光是"认卡"这一步就先卡住。这篇记的是给两天课程、40 个人共用一台机器部署大模型的全过程:从认卡、配 CANN、下模型、用 vLLM 起服务,到给 40 人做目录镜像和端口隔离。所有命令和参数都是真机实测,数据没动过。
你能直接拿去用的有这些:CANN 环境四条开机必做、1.5GB 模型下载三条路径的实测对比、vLLM 起 7B 对话服务与 0.5B 对照服务的完整 serve 参数、自写的 OpenAI 兼容向量服务、40 人隔离方案,还有 LoRA 微调 21 秒训完的甜点参数,以及 Ollama 在昇腾上的选型结论。
第一台机器拿到手,我敲的第一条命令是 nvidia-smi。
回来的是 command not found。
机器里装的是华为昇腾,一块 NVIDIA 的卡都没有。所有我背过的 CUDA 命令、所有教程里的 CUDA_VISIBLE_DEVICES、所有"一行命令起服务"的教程,从这一刻起全部作废。
我那套已经写好的部署脚本也因此整套作废。它是按 NVIDIA 写的,连最后一步的服务校验都是 nvidia-smi。后来按昇腾重写的版本,脚本名全部换成了 ascend_01 到 ascend_09。
一、先认卡:四条开机必做
1)看卡用 npu-smi info,不是 nvidia-smi。 而且要先 source 完 CANN 环境才能用。
2)起任何 NPU 进程前,必须 source 两个环境脚本:
set +u
source /usr/local/Ascend/cann/set_env.sh 2>/dev/null \
|| source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
set -u
少了 atb 那个,会报 libatb.so: cannot open shared object file。 而开头那个 set +u 也不能省:昇腾的 set_env.sh 内部引用了未定义变量,不开掉 nounset 就崩在这一行。
3)import torch_npu 不能省。 它是把 npu 设备注册进 torch 的插件,不 import,torch.npu.is_available() 会老老实实返回 False——然后你会以为这台机器根本没卡。
import torch
import torch_npu # 这行不能省
print(torch.npu.is_available())
4)python 和 vllm 都得用全路径。 直接敲 python3 拿到的是系统 3.10,里面没有 torch:
/usr/local/python3.11.14/bin/python3.11 -c "import torch; print(torch.__version__)" # 2.9.0+cpu
/usr/local/python3.11.14/bin/vllm --version # 0.11.0
顺手确认这两个也在:pip show torch-npu(2.9.0)、pip show vllm-ascend(0.19.1rc1)。
国产卡的第一个坑不在算力,在你对 NVIDIA 的肌肉记忆里。
二、网络不通:1.5GB 要下十几个小时
这台机器 github.com 和 huggingface.co 都不通。意思是:不能 from_pretrained 在线拉模型,也拉不到 GitHub release。
两条应对。
一是走代理,而且必须写死版本号:
https://ghproxy.net/https://github.com/<owner>/<repo>/releases/download/v0.19.1/xxx.tar.gz
写成 /releases/latest/... 经代理会 404,它跟不了重定向。
二是大文件一律走本机中转,别在服务器上硬拉。 这是我这次最省时间的一条,实测三条路:
| 路径 | 速度 | 1.5GB 耗时 |
|---|---|---|
| 服务器直连单连接 | 23 KB/s | 十几个小时 |
| 服务器并发分段(24 段) | ~130 KB/s | 3~8 小时且不稳 |
| 本机多线程下载 + SFTP 上传 | 14 MB/s 下行 | 约 15 分钟 |
差 600 倍。

顺带一个代价 3 小时的坑:并发分段把 390 段全下完了,拼接时用了 cat seg.*——那是字符串序(seg.0 seg.1 seg.10 …),拼出来顺序是乱的,zstd -t 必然失败。更蠢的是我的失败分支把全部分段删了。
要么用 for i in $(seq ...) 逐个追加,要么直接 seek 写单个文件。校验失败的时候别删分段。
三、起服务:vLLM 能起对话,起不了向量
对话服务这条实测 2.9 秒出回答:
/usr/local/python3.11.14/bin/vllm serve /model/models/Qwen2.5-7B-Instruct \
--served-model-name qwen2.5-7b \
--host 0.0.0.0 --port 8000 \
--max-model-len 16384 --max-num-seqs 32 \
--gpu-memory-utilization 0.85 \
--api-key 你的Key
--max-num-seqs 32 是并发上限,40 个人共用一个 7B 就靠这个扛,评测类的脚本错峰跑。
再起一个 0.5B 做"大小模型对照",只占一成显存:
/usr/local/python3.11.14/bin/vllm serve /model/qwen2.5-0.5b \
--served-model-name qwen2.5-0.5b \
--host 0.0.0.0 --port 8002 \
--max-model-len 4096 --max-num-seqs 16 \
--gpu-memory-utilization 0.10 \
--api-key 你的Key
但向量服务起不来:这一版 vllm-ascend 不认 --task embed,报 unrecognized arguments。我一开始就是照着 --task embed 写的,脚本跑空了一轮才发现。
解法是自己写一个:用 transformers + torch_npu 直接起一个 OpenAI 兼容的向量服务,Qwen3-Embedding-0.6B,1024 维。核心就三步:取 last_hidden_state 的最后一位、L2 归一化、套 OpenAI 的 /v1/embeddings 返回格式。对上层完全无感。
四、40 个人怎么共用一台机器

关键设计只有一条:远程目录刻意镜像本地目录。本地是 {代码包, 数据, 输出} 三级,服务器上是同样的三级,所以 notebook 里写死的 ../数据、../输出,传到服务器上一行都不用改。
建 40 个学员目录,核心就这几行:
SHARED=/data/fde/shared
for i in $(seq 1 40); do
d=/data/fde/students/$(printf "s%02d" $i)
mkdir -p "$d/代码包" "$d/输出" "$d/work"
ln -sfn $SHARED/data "$d/数据" # 软链共享,不是拷贝
cp -r $SHARED/代码包/. "$d/代码包/" # 代码每人一份副本
done
chmod -R a-w $SHARED/data # 共享数据只读,改了影响全班
| 隔离项 | 做法 |
|---|---|
| 代码 | 每人一份副本,共享区只读 |
| 数据 | 软链共享,只读,改了影响全班 |
| 产物 | 各写各的 输出/ |
| 端口 | 起 jupyter 用 88XX(XX = 自己的编号),避免互撞 |
| 微调 | 单卡按组排队,--out 必须指向自己目录 |
微调也是实测出来的甜点组合:240 条样本、3 轮、batch 4,0.5B 在 910B2 上 21 秒训完,loss 从 6.37 降到 0.60。
/usr/local/python3.11.14/bin/python3.11 finetune_lora.py \
--train ../输出/exp04_sft_train.jsonl \
--out ../输出/exp04_lora \
--base /model/qwen2.5-0.5b --epochs 3 --batch 4 \
--lr 2e-4 --lora-r 16 --lora-alpha 32 --max-len 512 --seed 42
可训练参数只有 1.08M,占总量 0.22%。
更省事的是:vLLM 已经占掉 85% 显存的情况下,这个 0.5B 的 LoRA 照样跑得动。所以不用为了演示微调去停 7B 服务。但 3B 以上会 OOM,要用 3B 必须先停 vLLM。
五、三个反直觉的结论
一、私有化的卖点不是"快",是"稳"。
同一句问题各测三次,本机直连:
| 端点 | 三次往返 |
|---|---|
| 自建服务器(7B) | 726 / 734 / 725 ms |
| 公有云在线 API | 1363 / 3445 / 2719 ms |
自有机器三次几乎不动,在线 API 波动 2.5 倍(排队加公网抖动)。

二、快不等于好。
7B 3394ms,0.5B 3096ms,几乎一样快。但 7B 的回答分步骤、会说"记录数据/分析原因",0.5B 也有步骤,只是更泛、更像模板。
时延接近是因为两者跑在同一块 NPU 上;差距在内容质量,不在速度。
三、换了 embedding 端点,必须重建向量。
两个 embedding 模型都是 1024 维,但实测余弦相似度只有 -0.02。

维度一样,不等于空间一样。带着旧向量切端点,检索会全部落空——表现出来是"全部拒答",你根本想不到问题出在向量上。
六、折腾一整夜,最后决定不用 Ollama
这条我最想记下来,因为它跟技术关系不大。
装 Ollama 试了五种方式,全失败:GitHub release 走代理只有 48–580KB/s 且停滞;官方 install.sh 是单连接流式,23KB/s;并发分段下完 390 段但拼错;本机下载再 SFTP 上传,传到一半本机出口被限流,服务端校验 Corrupted block;最后补齐 636MB,zstd -t 仍然报 Corrupted block。
真正让我决定砍掉的,不是"没装上",是算清了一笔账:Ollama 在昇腾上只能跑 CPU。也就是说,就算装成了,收益也薄得可怜。
于是改成:课上一律用 vLLM,Ollama 只留一张选型对比表讲定位,那批脚本标记弃用、不再维护。
沉没成本不是继续的理由。先算"装成了能好多少",再决定要不要接着装。
七、值得这么折腾吗
值得:要做国产化适配、要一批人共用一张卡、要跑微调、环境不能联网。
不值得:只是想本地跑个小模型玩玩。你自己电脑上装什么都比这快,别租服务器。
一个前提:动手前先确认机器到底是什么卡。这一步省下的时间,比后面所有优化加起来都多。
先看清你脚下站的是什么卡,再决定怎么迈腿。
本文为个人真机实测记录,命令与数据均来自实际部署过程,供国产算力环境部署参考。
更多推荐




所有评论(0)