在国产算力平台上部署大规模语言模型,往往被视为一项充满挑战的系统工程。与成熟的CUDA生态相比,昇腾CANN环境的配置细节确实存在差异,但这并不意味着门槛高不可攀。实际上,只要掌握了正确的工具链和依赖管理逻辑,在昇腾910B上跑通DeepSeek-7B甚至67B模型,完全可以在一个下午内完成。本篇将剥离繁杂的理论,以实战视角还原从环境检查到首个Token生成的全过程。

部署前的“体检”:环境就绪性验证

在开始任何安装之前,确认硬件与驱动状态是绝对的第一步。很多看似诡异的运行错误,根源往往是驱动版本与固件不匹配。我们需要习惯使用 npu-smi 工具来进行“体检”。

在终端输入 npu-smi info,这相当于NPU的听诊器。你需要重点关注 Version 栏目下的驱动版本号,以及 Health 状态是否为 OK。对于DeepSeek这类大模型,建议CANN版本不低于7.0,因为新版算子库对Transformer架构的优化更为激进。如果发现某张卡的显存占用异常(非0且无进程),使用 npu-smi info -t memory -i <device_id> 可以进一步排查残留进程,必要时进行清理,确保我们是在一张干净的白纸上作画。

核心依赖链:构建稳固的运行时环境

昇腾环境的特殊性在于“PyTorch适配器”这一层。我们不能直接使用官方的PyTorch,而需要安装华为提供的 torch_npu 插件。这个插件的作用是将PyTorch的标准算子调用,“翻译”成NPU能够理解的底层指令。

构建环境时,推荐使用Conda创建一个隔离的沙盒,避免污染系统库。

# 创建并激活虚拟环境
conda create -n deepseek_env python=3.9
conda activate deepseek_env

# 安装PyTorch(需根据CANN版本选择对应whl包)
# 假设CANN版本为7.0.RC1
pip install torch==2.1.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install torch_npu-2.1.0.post1-cp39-cp39-linux_aarch64.whl

# 安装DeepSpeed(昇腾适配版)
pip install deepspeed_npu

这里有一个极易被忽视的细节:source /usr/local/Ascend/ascend-toolkit/set_env.sh 这个环境变量加载命令,必须写入到 ~/.bashrc 或启动脚本中。缺少这一步,即使包安装得再完美,Python解释器也找不到底层的算子库文件,报错通常是晦涩难懂的 Symbol not found

模型权重准备:从下载到格式转换

DeepSeek的模型权重通常托管在Hugging Face或ModelScope。在内网环境或下载速度受限时,ModelScope往往是更好的选择。下载完成后,我们面临的一个关键决策是:是否需要转换权重格式?

大多数情况下,直接加载HF格式的权重在 torch_npu 上是可行的,但在追求极致性能时,将其转换为昇腾友好的Safetensors格式,并进行适当的分片处理,可以显著提升加载速度。

from modelscope import snapshot_download
model_dir = snapshot_download('deepseek-ai/deepseek-llm-7b-chat', cache_dir='./weights')

对于部分依赖Flash Attention算子的高性能实现,可能需要确认权重配置中的 rope_scaling 参数是否与NPU算子支持的范围一致。如果遇到形状不匹配的报错,检查 config.json 中的 num_key_value_heads 是否被正确识别是排查的关键方向。

推理脚本编写:让模型“开口说话”

万事俱备,只欠东风。编写推理脚本时,核心改动在于指定设备为 npu。不要惯性地使用 .cuda(),在昇腾世界里,.npu() 才是通用的方言。

import torch
import torch_npu
from transformers import AutoTokenizer, AutoModelForCausalLM

# 指定使用NPU设备
device = torch.device("npu:0")

# 加载模型与分词器
model_path = "./weights/deepseek-llm-7b-chat"
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    trust_remote_code=True
).to(device)

# 构造Prompt
prompt = "你好,请介绍一下昇腾910B芯片的特点。"
inputs = tokenizer(prompt, return_tensors="pt").to(device)

# 执行推理
# 此时NPU开始高速运转,显存占用会瞬间飙升
outputs = model.generate(
    **inputs, 
    max_new_tokens=200,
    repetition_penalty=1.1
)

response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)

当你运行这段脚本,看到控制台输出流畅的中文回答时,恭喜你,你已经打通了从通用算力到国产算力的“最后一公里”。

进阶优化:开启高性能模式

跑通只是开始,跑得快才是目的。在验证了基础流程后,我们通常会引入 torch.compile 或昇腾特有的 jit 编译模式来加速推理。

一个立竿见影的优化动作是开启“算子融合”。通过设置环境变量 export ASCEND_GLOBAL_LOG_LEVEL=3 屏蔽冗余日志,并使用 acl_transformer 库(如果有集成)来替换原生Transformer层,由于减少了Python层面的调度开销,推理延迟(Latency)往往能降低30%以上。

此外,DeepSeek模型支持长上下文,这会带来巨大的显存压力。在启动脚本中合理设置 PYTORCH_NPU_ALLOC_CONF=expandable_segments:True,可以让显存分配器更加灵活地处理碎片,避免明明有剩余显存却报OOM的尴尬情况。

部署DeepSeek到昇腾平台,本质上是一次对软硬结合能力的重塑。当你习惯了这套工具链,会发现它在很多垂直场景下,提供了不输甚至优于通用方案的性价比与可控性。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐