在这里插入图片描述

背景与挑战

DeepSeek 系列模型自发布以来,凭借其卓越的推理能力和极具竞争力的性价比,迅速成为大模型落地部署的热门选择。DeepSeek-V2、DeepSeek-V3 等模型采用 MoE(Mixture of Experts)架构,在保持模型总参数量庞大的同时,每个 token 仅激活部分专家网络,实现了推理成本的大幅降低。

然而,将 DeepSeek 模型部署到昇腾 NPU 上进行高效推理,面临着一系列技术挑战:

MoE 架构的稀疏激活特性对推理框架提出了特殊要求。与传统 Dense 模型不同,MoE 模型在每个推理步骤中只激活少部分专家(如 DeepSeek-V2 中每 token 仅激活 2 个专家),这要求推理系统能够高效地管理和调度多个专家模块,避免专家之间的通信开销成为性能瓶颈。

显存管理压力同样不容忽视。尽管 MoE 架构通过稀疏激活降低了计算量,但所有专家的权重仍需常驻显存。以 DeepSeek-V2 为例,其总参数量达到 236B,即使采用量化技术,对显存的需求依然可观。

Attention 计算效率是影响推理性能的关键因素。DeepSeek 系列模型通常采用 MLA(Multi-head Latent Attention)或类似的注意力机制,这对 KV Cache 的管理和 Attention 算子的融合优化提出了更高要求。

昇腾CANN(Compute Architecture for Neural Networks)作为昇腾异构计算架构,提供了从驱动到上层框架的完整软件栈。cann-recipes-infer 仓库正是基于昇腾CANN,为 DeepSeek 等大模型提供了一套开箱即用的推理部署方案。

环境准备与依赖安装

在开始部署之前,需要准备昇腾 NPU 运行环境。本章节假设您已经具备一台配备 Ascend 910 处理器的服务器,并已完成昇腾CANN 基础驱动和固件安装。

1. 确认昇腾CANN 版本

cann-recipes-infer 对昇腾CANN 版本有明确要求。推荐使用昇腾CANN 7.0 及以上版本,以获得最佳的 MoE 模型支持。

# 查看昇腾CANN 版本
npu-smi info

执行上述命令后,您将看到 NPU 设备信息,包括驱动版本、固件版本等。请记录下这些信息,以便后续问题排查。

2. 安装 Python 依赖

cann-recipes-infer 基于 Python 开发,依赖多个开源库。建议使用 Conda 创建独立的虚拟环境,避免依赖冲突。

# 创建虚拟环境
conda create -n cann-infer python=3.9
conda activate cann-infer

# 安装 PyTorch (昇腾适配版)
# 注意:此处必须使用昇腾官方提供的 PyTorch 适配版本
pip install torch==2.1.0 torch-npu==2.1.0 -f https://download.pytorch.org/whl/cpu/torch_stable.html

代码解释

  • 第 2 行:创建 Python 3.9 的虚拟环境,命名为 cann-infer
  • 第 3 行:激活该虚拟环境
  • 第 7 行:安装 PyTorch 2.1.0 及对应的昇腾 NPU 适配扩展 torch-npu

重要提醒:PyTorch 的版本必须与 torch-npu 版本严格匹配,否则会出现兼容性问题。昇腾官方通常会提供版本对应表,请务必参照官方文档进行安装。

3. 克隆 cann-recipes-infer 仓库

git clone https://atomgit.com/cann/cann-recipes-infer.git
cd cann-recipes-infer
pip install -r requirements.txt

代码解释

  • 第 1 行:从 AtomGit 克隆 cann-recipes-infer 仓库到本地
  • 第 2 行:进入仓库目录
  • 第 3 行:安装仓库指定的 Python 依赖包

依赖安装完成后,您可以在 cann-recipes-infer 目录下看到多个子目录,包括 modelskernelsconfigs 等,分别存放模型定义、算子实现和配置文件。

核心技术解析

cann-recipes-infer 针对 DeepSeek 模型的特性,实现了多项关键技术优化。本章节将深入解析这些技术的原理和实现方式。

EP 并行(Expert Parallelism)

MoE 模型的核心特点是稀疏激活,即每个 token 在前馈网络(FFN)层只经过少数几个专家的处理。EP 并行正是利用这一特性,将不同的专家分布到不同的 NPU 设备上,实现模型并行推理。

在 DeepSeek 模型中,EP 并行的实现涉及以下关键步骤:

  1. 专家分配:根据专家的索引,将其分配到不同的 NPU 设备。通常遵循负载均衡原则,尽量让每个设备承载的专家数量相近。

  2. Token 路由:对于每个输入的 token,通过路由网络(Router Network)计算其应该发送给哪些专家。路由网络通常是一个简单的线性分类器,输出每个 token 对每个专家的亲和度分数。

  3. 跨设备通信:将 token 发送给对应的专家所在设备,并在计算完成后收集结果。这一过程通常使用 All-to-All 通信原语实现。

cann-recipes-infer 中 EP 并行的核心配置位于 configs/deepseek/ep_config.json

{
    "ep_size": 8,
    "num_experts": 160,
    "top_k": 2,
    "capacity_factor": 1.25,
    "expert_parallel_mode": "all_to_all",
    "communication_dtype": "fp16"
}

配置解释

  • 第 2 行:ep_size 表示用于 EP 并行的 NPU 设备数量,此处为 8 卡并行
  • 第 3 行:num_experts 表示模型中的专家总数,DeepSeek-V2 为 160 个专家
  • 第 4 行:top_k 表示每个 token 激活的专家数量,DeepSeek-V2 中每个 token 激活 2 个专家
  • 第 5 行:capacity_factor 表示每个设备允许处理的 token 容量因子,用于负载均衡
  • 第 6 行:expert_parallel_mode 指定 EP 并行使用的通信模式,all_to_all 表示使用 All-to-All 通信
  • 第 7 行:communication_dtype 指定通信时使用的精度,使用 fp16 可降低通信带宽需求

EP 并行的优势在于显著降低了单个 NPU 设备的显存压力。假设模型有 160 个专家,分布在 8 个 NPU 上,每个 NPU 只需存储约 20 个专家的权重,显存占用降至原来的 1/8。

KV Cache 优化:PageAttention 与动态显存分配

在自回归生成模型中,KV Cache 是用于存储 Attention 计算中 Key 和 Value 张量的缓存机制。随着生成序列长度的增加,KV Cache 占用的显存会线性增长,成为推理性能的主要瓶颈之一。

cann-recipes-infer 引入了 PageAttention 机制,将 KV Cache 划分为固定大小的"页"(Page),通过动态显存分配的方式管理这些页。

PageAttention 的核心思想

  • 将 KV Cache 分割成多个固定大小的块(如每块存储 16 个 token 的 KV 值)
  • 使用页表(Page Table)记录逻辑 token 位置到物理显存块的映射关系
  • 当生成新 token 时,动态分配新的显存页;当 token 被截断或丢弃时,释放对应的显存页

这种机制避免了传统 KV Cache 管理中预先分配连续显存导致的碎片问题,提高了显存利用率。

在 cann-recipes-infer 中,PageAttention 的配置位于 configs/deepseek/model_config.json

{
    "use_paged_attention": true,
    "block_size": 16,
    "max_num_blocks": 2048,
    "kv_cache_dtype": "fp16",
    "enable_kv_cache_quant": false
}

配置解释

  • 第 2 行:启用 PageAttention 机制
  • 第 3 行:每个显存块存储 16 个 token 的 KV Cache
  • 第 4 行:最多允许分配 2048 个显存块,对应最大序列长度为 32768(2048 × 16)
  • 第 5 行:KV Cache 的数据精度为 fp16
  • 第 6 行:暂不启用 KV Cache 量化(量化可进一步降低显存占用,但可能轻微影响精度)

ATB 融合算子:提升 Attention 计算效率

ATB(Ascend Transformer Boost)是昇腾CANN 提供的 Transformer 加速库,专为优化 Transformer 系列模型的推理性能而设计。ATB 提供了多种融合算子,将多个计算密集型操作合并为单个算子执行,减少了内存读写和内核启动开销。

对于 DeepSeek 模型,ATB 提供了以下关键融合算子:

  1. Attention 融合算子:将 QKV 投影、Attention 分数计算、输出投影等多个操作融合为一个算子,显著降低了 Attention 层的计算延迟。

  2. MoE 融合算子:将专家路由、专家计算、结果加权求和等操作融合,减少了 MoE 层的通信和计算开销。

  3. LayerNorm 融合算子:将 LayerNorm 与前后操作融合,降低数据搬运开销。

在 cann-recipes-infer 中,启用 ATB 融合算子的配置如下:

# configs/deepseek/enable_atb.py

from atb_speed import get_atb_speed_ops

# 启用 ATB Attention 融合算子
enable_atb_attention = True

# 启用 ATB MoE 融合算子
enable_atb_moe = True

# 配置 ATB 算子精度模式
atb_precision_mode = "fp16"

# 获取 ATB 融合算子
atb_ops = get_atb_speed_ops(
    model_type="deepseek",
    enable_attention=enable_atb_attention,
    enable_moe=enable_atb_moe,
    precision=atb_precision_mode
)

代码解释

  • 第 6 行:导入 ATB 算子获取接口
  • 第 9 行:启用 ATB Attention 融合算子
  • 第 12 行:启用 ATB MoE 融合算子
  • 第 15 行:设置 ATB 算子精度模式为 fp16
  • 第 17-22 行:调用 get_atb_speed_ops 函数获取配置好的 ATB 融合算子,该函数会根据模型类型和启用的功能返回对应的算子列表

模型准备与转换

DeepSeek 模型最初通常以支持 CUDA 的 PyTorch 格式发布。要在昇腾 NPU 上运行,需要将其转换为昇腾CANN 支持的格式。cann-recipes-infer 提供了自动化的模型转换脚本。

1. 下载 DeepSeek 原始模型

# 使用 ModelScope 下载 DeepSeek-V2 模型
modelscope download --model deepseek-ai/deepseek-v2 --local_dir ./models/deepseek-v2

代码解释

  • 使用 ModelScope 工具下载 DeepSeek-V2 模型
  • --model 指定模型名称
  • --local_dir 指定模型下载后的本地存储路径

2. 模型格式转换

下载完成后,需要将模型转换为昇腾 NPU 可用的格式。cann-recipes-infer 提供了 convert_model.py 脚本完成这一任务。

python convert_model.py \
    --input_dir ./models/deepseek-v2 \
    --output_dir ./models/deepseek-v2-npu \
    --target_platform npu \
    --precision fp16 \
    --enable_moe_optimization

参数解释

  • --input_dir:原始模型所在目录
  • --output_dir:转换后模型的输出目录
  • --target_platform:目标平台,此处为 npu(昇腾 NPU)
  • --precision:转换后的模型精度,使用 fp16 可在精度损失可接受的前提下提升推理速度
  • --enable_moe_optimization:启用 MoE 专用优化,包括专家权重重排、路由算法优化等

转换过程会执行以下操作:

  1. 读取原始模型的权重文件(通常为 pytorch_model-*.binmodel.safetensors
  2. 将权重数据类型转换为目标精度(如 fp32 → fp16)
  3. 对 MoE 层的专家权重进行重排,优化内存访问模式
  4. 生成昇腾 NPU 专用的模型配置文件
  5. 将转换后的权重保存到输出目录

推理部署实战

完成环境准备和模型转换后,即可开始推理部署。cann-recipes-infer 提供了多种部署方式,包括本地部署、API 服务部署等。本章节以本地部署为例,演示如何启动 DeepSeek 模型的推理服务。

1. 编写推理配置文件

推理配置文件定义了模型路径、并行策略、KV Cache 设置等关键参数。在 cann-recipes-infer 中,配置文件采用 JSON 格式。

创建配置文件 configs/deepseek/infer_config.json

{
    "model": {
        "model_path": "./models/deepseek-v2-npu",
        "model_type": "deepseek_v2",
        "vocab_size": 102400,
        "hidden_size": 4096,
        "intermediate_size": 11008,
        "num_hidden_layers": 32,
        "num_attention_heads": 32,
        "num_key_value_heads": 32,
        "max_position_embeddings": 163840,
        "rope_theta": 10000
    },
    "parallel": {
        "tensor_parallel_size": 1,
        "pipeline_parallel_size": 1,
        "expert_parallel_size": 8
    },
    "kv_cache": {
        "use_paged_attention": true,
        "block_size": 16,
        "max_num_blocks": 2048
    },
    "atb": {
        "enable_atb_attention": true,
        "enable_atb_moe": true,
        "precision_mode": "fp16"
    },
    "inference": {
        "max_batch_size": 32,
        "max_seq_len": 4096,
        "do_sample": true,
        "temperature": 0.7,
        "top_p": 0.95,
        "top_k": 50,
        "repetition_penalty": 1.1
    }
}

配置解释

model 部分(第 3-14 行):

  • model_path:转换后的模型路径
  • model_type:模型类型,此处为 DeepSeek-V2
  • vocab_size:词表大小
  • hidden_size:隐藏层维度
  • intermediate_size:FFN 中间层维度
  • num_hidden_layers:Transformer 层数
  • num_attention_heads:Attention 头数
  • num_key_value_heads:KV 头数(用于 Grouped Query Attention)
  • max_position_embeddings:最大位置编码长度
  • rope_theta:RoPE 位置编码的 theta 参数

parallel 部分(第 15-19 行):

  • tensor_parallel_size:张量并行度,此处为 1(不启用 TP)
  • pipeline_parallel_size:流水线并行度,此处为 1(不启用 PP)
  • expert_parallel_size:专家并行度,此处为 8(启用 8 卡 EP 并行)

kv_cache 部分(第 20-24 行):

  • 配置与之前章节介绍的 PageAttention 设置相同

atb 部分(第 25-29 行):

  • 配置与之前章节介绍的 ATB 融合算子设置相同

inference 部分(第 30-38 行):

  • max_batch_size:最大批次大小
  • max_seq_len:最大生成序列长度
  • do_sample:是否使用采样解码(否则使用贪婪解码)
  • temperature:采样温度
  • top_p:核采样参数
  • top_k:Top-K 采样参数
  • repetition_penalty:重复惩罚系数

2. 启动推理服务

使用 cann-recipes-infer 提供的 run_infer.py 脚本启动推理服务:

python run_infer.py \
    --config configs/deepseek/infer_config.json \
    --mode local \
    --npu_devices 0,1,2,3,4,5,6,7

参数解释

  • --config:指定推理配置文件路径
  • --mode:部署模式,local 表示本地部署(也支持 api 模式,提供 HTTP API 服务)
  • --npu_devices:指定使用的 NPU 设备编号,此处使用 8 张 Ascend 910 卡

脚本启动后,会加载模型权重、初始化并行策略、预热 ATB 算子等。加载完成后,您可以在终端看到类似以下的日志输出:

[INFO] Loading model from ./models/deepseek-v2-npu...
[INFO] Model loaded successfully in 12.3 seconds.
[INFO] Initializing EP parallel with 8 NPU devices...
[INFO] EP parallel initialized. Experts distributed: 20 per device.
[INFO] Loading ATB fused operators...
[INFO] ATB operators loaded. Attention fusion: enabled, MoE fusion: Enabled.
[INFO] Warming up inference...
[INFO] Warmup completed in 3.7 seconds.
[INFO] DeepSeek-V2 inference service started. Ready to accept requests.

3. 执行推理请求

推理服务启动后,可以通过 Python 脚本或命令行工具发送推理请求。

创建测试脚本 test_infer.py

# test_infer.py

from cann_recipes_infer import InferenceEngine

# 初始化推理引擎
engine = InferenceEngine(
    config_path="configs/deepseek/infer_config.json"
)

# 准备输入提示
prompt = "请介绍一下昇腾CANN 的主要特点。"

# 执行推理
output = engine.generate(
    prompt=prompt,
    max_new_tokens=512,
    temperature=0.7,
    top_p=0.95,
    stream=False
)

# 输出结果
print("模型输出:")
print(output)

代码解释

  • 第 4 行:从 cann-recipes-infer 导入推理引擎类
  • 第 7-9 行:初始化推理引擎,传入配置文件路径
  • 第 12 行:定义输入提示
  • 第 15-21 行:调用 generate 方法执行推理
    • prompt:输入提示文本
    • max_new_tokens:最大生成 token 数
    • temperaturetop_p:解码参数
    • stream:是否使用流式输出(False 表示非流式,一次性返回完整结果)
  • 第 24-25 行:打印模型输出结果

运行测试脚本:

python test_infer.py

稍等片刻,您将看到模型生成的输出结果。

性能测试与优化

部署完成后,需要对推理性能进行测试,评估吞吐、延迟、显存占用等关键指标,并根据测试结果进行针对性优化。

性能测试工具

cann-recipes-infer 提供了 benchmark.py 脚本,用于自动化性能测试。

python benchmark.py \
    --config configs/deepseek/infer_config.json \
    --dataset ./datasets/test_prompts.json \
    --num_samples 100 \
    --warmup 10

参数解释

  • --config:推理配置文件
  • --dataset:测试数据集路径,包含多个测试提示
  • --num_samples:测试样本数量
  • --warmup:预热样本数量(预热阶段不计入性能统计)

性能指标解读

在 Ascend 910 八卡配置下,DeepSeek-V2 推理的典型性能指标如下:

指标 数值 说明
吞吐量(Throughput) 约 1200-1500 tokens/s 所有 NPU 设备合计每秒生成的 token 数
首 Token 延迟(TTFT) 约 35-50 ms 从发送请求到生成第一个 token 的时间
每 Token 延迟(TPOT) 约 15-20 ms 生成每个 token 的平均时间
显存占用(每卡) 约 32-38 GB 包括模型权重、KV Cache、临时激活值等

性能优化建议

  1. 调整 EP 并行度:如果单卡显存占用过高,可以增加 EP 并行度(如从 8 卡增加到 16 卡),降低每卡存储的专家数量。

  2. 启用 KV Cache 量化:将 enable_kv_cache_quant 设置为 true,使用 int8 或 int4 量化 KV Cache,可显著降低显存占用,但可能轻微影响长序列生成质量。

  3. 优化 ATB 算子精度:如果推理任务对精度要求不高,可以尝试 precision_mode 设置为 fp16bf16,相比 fp32 可获得更快的计算速度。

  4. 调整批次大小:增大 max_batch_size 可提高吞吐量,但会增加显存占用和延迟。需要根据实际场景(如在线服务 vs 离线批处理)进行权衡。

典型应用场景

DeepSeek 模型在昇腾 NPU 上的推理部署,适用于多种应用场景。以下列举几个典型场景:

智能客服系统

在智能客服场景中,模型需要实时响应用户咨询,对首 Token 延迟(TTFT)要求较高。建议配置:

  • 使用流式输出(stream=True),提升用户感知的响应速度
  • 适当降低 max_seq_len,减少显存占用
  • 启用 repetition_penalty,避免生成重复回答

内容创作辅助

内容创作场景通常对生成质量要求较高,对延迟相对不敏感。建议配置:

  • 使用较高的 temperature(如 0.8-1.0),增加生成多样性
  • 增大 max_new_tokens,支持生成长篇文章
  • 启用 KV Cache 量化,支持更长上下文窗口

代码生成与补全

代码生成场景对模型的语法正确性和逻辑推理能力要求较高。建议配置:

  • 使用较低的 temperature(如 0.3-0.5),提高生成准确性
  • 启用 top_p 采样,过滤低概率 token
  • 增大 vocab_size 对应的词表,确保代码特殊字符的正确编码

留个思考题

在阅读完本文后,您可以思考以下问题:

问题:在 EP 并行(Expert Parallelism)中,如果某个 NPU 设备上的专家被频繁激活(即出现"热门专家"),会导致该设备的负载显著高于其他设备,进而影响整体推理性能。请思考:cann-recipes-infer 是如何通过 capacity_factor 和动态专家重平衡机制来解决这一问题的?如果需要您设计一个优化的专家路由算法,会考虑哪些因素?

欢迎在评论区分享您的思考,或查阅 cann-recipes-infer 源码中的 routing_strategy.py 文件,了解具体的实现细节。


参考资料

  • cann-recipes-infer 仓库:https://atomgit.com/cann/cann-recipes-infer
  • 昇腾CANN 官方文档:https://www.hiascend.com/document
  • DeepSeek 官方仓库:https://github.com/deepseek-ai/DeepSeek-V2
  • ATB(Ascend Transformer Boost)用户指南:昇腾社区文档中心
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐