Skip to content

feat: support deepSeek-v3.2 w8a8 pytorch adaptation on npu - #2076

Open
sunbaosong wants to merge 1 commit into
xLLM-AI:mainfrom
sunbaosong:base-pr2009
Open

feat: support deepSeek-v3.2 w8a8 pytorch adaptation on npu#2076
sunbaosong wants to merge 1 commit into
xLLM-AI:mainfrom
sunbaosong:base-pr2009

Conversation

@sunbaosong

@sunbaosong sunbaosong commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

背景

在 Ascend NPU 上落地 DeepSeek-V3.2 W8A8,新增 deepseek_v32 模型(PyTorch 组图路径),支持单卡与多节点 TP,并与 vllm 数值对齐。

代码改动

本 PR 重点完成 DeepSeek-V3.2 W8A8 在 xllm 框架侧的落地,核心改动如下:

1. 框架侧 KV cache 新增 index_cache 传入

为支撑稀疏 MLA(latent 空间 attention 选 top-k KV),KV cache 由 (k, v) 升级为 (k, v, index_cache)index_cache 承载
indexer 选出的 top-k KV 索引,供后续 decode 复用。C++ 侧 py_executor_impl.cpp 同步扩展,Python 侧模型 / attention
路径透传 index_cache

2. 新增 lightning_indexer 算子

新增 lightning_indexer 算子(C++ lightning_indexer.cpp + xllm_ops_api.h 声明 + Python ops/compute.py 封装),对接
CANN aclnnLightningIndexer,在稀疏 MLA 中按 query 选 top-k KV 槽位写入 index_cache

3. 新增 / 注册若干 W8A8 算子

npu_ops_library.cpp 注册本模型所需的 W8A8 / MLA / MoE 算子 schema 与 NPU adapter,Python 侧 ops/compute.py
提供封装(含 register_fake):

  • quant_matmul(静态 W8A8 matmul)
  • quantize_per_tensor / dynamic_quant(per-tensor / per-token 激活量化)
  • lightning_indexer(含 pre_tokens / next_tokens / return_value 等参数)
  • scatter_nd_update
  • sparse_flash_attention(在 npu_ops_library.cpp 注册 schema + NPU adapter,绑定已有 kernel)

ops/collectives.py 新增 tp_rank,供多节点权重分片与 row-parallel 量化偏置门控使用。

4. DSV3.2 模型结构适配

新增 xllm/python/models/deepseek_v32.py,按 DeepSeek-V3.2 结构组织 absorbed-form MLA、稀疏 indexer、稀疏 attention、dense
MLP 与纯 TP MoE,前向经 PyExecutorImpl 驱动 Python 图执行;model_registrymodel_registry.cpp / registry.py)注册
deepseek_v32(torch + ATB 双后端),走 --model_impl=python 路径实例化。

5. 多节点权重分片

权重分片改用框架全局 tp_rankconfig["tp_rank"] =
tp_group_->rank()),保证跨节点分片唯一、专家权重完整加载;框架未注入时回退设备 index(单节点 local==global)。

使用的镜像

quay.io/jd_xllm/xllm-ai:xllm-dev-a2-arm-cann9-20260605

openEuler 24.03 LTS-SP2 aarch64 + CANN 9.0。

启动配置

模型走 PyTorch 组图路径:--model_impl=pythonPyCausalLMregistry.get_model_class("deepseek_v32") 实例化
DeepseekV3ForCausalLM

#️## 前置

️- 编译:python setup.py build(产出 build/xllm/core/server/xllm)。

双机(2 节点 × 8 卡 = 16 NPU)

每节点起 1 份脚本(master + worker),每节点本地循环起 LOCAL_NODES 个进程,--devices=npu:$DEVICE
显式指定本机卡,--node_rank 全局唯一(master 0..7、worker 8..15),--host 为本机 IP,--master_node_addr
两边一致,--rank_tablefile 指向同一份 ranktable。

master 节点(node 0)

export XLLM_PYTHON_MODEL_PATH=<repo_root>
XLLM_PATH=<repo_root>/build/xllm/core/server/xllm
MODEL_PATH=<dsv32_w8a8_权重目录>
MASTER_NODE_ADDR="<master_ip>:19990"   # 两节点一致
LOCAL_HOST="<master_ip>"
NNODES=16; LOCAL_NODES=8; START_PORT=15890; START_DEVICE=0
LOG_DIR=<...>/logs/master; mkdir -p $LOG_DIR

for ((i=0; i<LOCAL_NODES; i++)); do
  PORT=$((START_PORT + i)); DEVICE=$((START_DEVICE + i))
  nohup $XLLM_PATH \
    --model $MODEL_PATH --model_impl=python \
    --host $LOCAL_HOST --port $PORT --devices="npu:$DEVICE" \
    --master_node_addr=$MASTER_NODE_ADDR --nnodes=$NNODES \
    --node_rank=$i \
    --max_memory_utilization=0.85 --block_size=128 \
    --communication_backend=hccl \
    --enable_prefix_cache=false --enable_chunked_prefill=false \
    --enable_schedule_overlap=false --enable_graph=false \
    --rank_tablefile=<repo_root>/conf/ranktable.json \
    > $LOG_DIR/node_$i.log 2>&1 &
done

worker 节点(node 1)

# 同上,仅改:LOCAL_HOST="<worker_ip>";--node_rank=$((i + LOCAL_NODES))

#️## 就绪检查 / 请求

curl -s --max-time 5 http://127.0.0.1:18001/v1/models
curl -s http://127.0.0.1:18001/v1/chat/completions -H "Content-Type: application/json" \
  -d '{"model":"deepseek_v32","messages":[{"role":"user","content":"hi"}],"max_tokens":32}'
image

验证

  • 单卡 + TP=2 与 vllm 5L greedy token bit-exact
  • 16-NPU 多节点输出可读。

Comment thread xllm/core/kernels/npu/xllm_ops/lightning_indexer.cpp Outdated
@sunbaosong
sunbaosong force-pushed the base-pr2009 branch 3 times, most recently from 574b9a5 to 0502c97 Compare July 30, 2026 08:58
@sunbaosong
sunbaosong marked this pull request as ready for review July 30, 2026 11:10
@sunbaosong sunbaosong changed the title WIP: support deepseek v3.2 used Pytorch model feat: DeepSeek-V3.2 W8A8 NPU PyTorch 组图 适配 Jul 30, 2026
@sunbaosong sunbaosong changed the title feat: DeepSeek-V3.2 W8A8 NPU PyTorch 组图 适配 feat: Support DeepSeek-V3.2 W8A8 PyTorch adaptation on NPU Jul 30, 2026
@sunbaosong sunbaosong changed the title feat: Support DeepSeek-V3.2 W8A8 PyTorch adaptation on NPU feat: support deepSeek-v3.2 w8a8 pytorch adaptation on npu Jul 30, 2026
Comment thread xllm/python/models/deepseek_v32.py
Comment thread xllm/python/models/deepseek_v3.py Outdated
sunbaosong added a commit to sunbaosong/xllm that referenced this pull request Jul 31, 2026
- Rename xllm/python/models/deepseek_v3.py -> deepseek_v32.py to match
  the registered model name "deepseek_v32"; update the lazy import in
  xllm/python/registry.py accordingly.
- Drop the module-level _TP_SIZE / _ACL_FORMAT_FRACTAL_NZ constants and
  inline their only use sites: tp_size default -> 1, npu_format_cast
  format -> 29 (ACL_FORMAT_FRACTAL_NZ), in line with the repo's existing
  C++ loaders.

Co-Authored-By: Claude <noreply@anthropic.com>
sunbaosong added a commit to sunbaosong/xllm that referenced this pull request Jul 31, 2026
- Rename xllm/python/models/deepseek_v3.py -> deepseek_v32.py to match
  the registered model name "deepseek_v32"; update the lazy import in
  xllm/python/registry.py accordingly.
- Drop the module-level _TP_SIZE / _ACL_FORMAT_FRACTAL_NZ constants and
  inline their only use sites: tp_size default -> 1, npu_format_cast
  format -> 29 (ACL_FORMAT_FRACTAL_NZ), in line with the repo's existing
  C++ loaders.
@sunbaosong
sunbaosong force-pushed the base-pr2009 branch 2 times, most recently from ab7eccd to 9fcc78a Compare July 31, 2026 06:56
基于 PyTorch 组图(--model_impl=python,Python 模型执行器构建前向图,非 ATB
C++ 图后端)在 Ascend NPU 上落地 DeepSeek-V3.2 W8A8,实现 absorbed-form
MLA、稀疏 indexer、纯 TP MoE,并使 xllm 与 vllm 在单卡 / TP=2 / 多节点下
数值对齐。

- absorbed-form MLA + W8A8(静态/动态)+ MoE int8-grouped + TP 适配
  (npu_grouped_matmul / npu_moe_init_routing_v2 / npu_moe_token_unpermute /
  npu_dynamic_quant / aclnnLightningIndexer / aclnnSparseFlashAttention)。
- TP 对齐方案:o_proj quant_bias 按 tp_rank==0 门控;routed_scaling 在
  combine 后、all_reduce 前应用;AR 用 sum-then-reduce。单卡 + TP=2 与
  vllm 在 gate→topk→dispatch→gmm1→gmm2→combine→AR 全链路 bit-exact。
- 多节点:权重分片使用框架全局 tp_rank(config["tp_rank"] =
  tp_group_->rank()),保证跨节点分片唯一、专家权重完整加载。
- 新增 ops(quant_matmul / quantize_per_tensor / dynamic_quant /
  lightning_indexer / scatter_nd_update / sparse_flash_attention + tp_rank)
  及 CANN 9.0 SFA 新签名对齐;注册 deepseek_v32(torch + ATB 双后端)。
- 启动:--model_impl=python 走 PyTorch 组图,--enable_graph=false eager;
  单卡单进程,TP=2 多进程(node_rank % 可见卡数 选卡)。

验证:单卡 + TP=2 与 vllm 5L bit-exact;16-NPU 双节点输出可读。
return self._prefill(q_3d, k_3d, v_3d, metadata, num_tokens)
return self._decode(q_3d, k_cache, v_cache, metadata, num_tokens)

def execute_mla(

@zhang-minchao zhang-minchao Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的 execute_mla() 实际承载的是 LightningIndexer 驱动的 Sparse MLA/SFA,而不只是通用 MLA。建议将 LightningIndexer 设计为 Sparse MLA 的可组合组件,而不是把 index cache、top-k 选择和 sparse attention 都继续加入 NpuPagedAttentionBackend,也不要由模型直接访问 backend._metadatabackend._kv_caches 来完成组合。

可以参考 vLLM 的 MLAModules(indexer=...) / MultiHeadLatentAttentionWrapper:Indexer 保持独立组件和独立 cache 语义,由 Sparse MLA layer 组合;vllm-ascend 则通过 AscendSFAImpl 统一协调 index cache 更新、LightningIndexer 和 Sparse Flash Attention。建议 xLLM 对应拆分为通用 MLAAttention 和组合 LightningIndexer 的 SparseMLAAttention/NpuSFABackend。这样 dense MLA 可以复用同一 MLA 抽象而不依赖 Indexer,DeepSeek-V3.2 的 sparse 路径也能通过公开 contract 完成完整执行链。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants