ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

昇腾 NPU 模型推理运行时错误诊断与修复实战:基于 CANN cann-recipes-infer 的 aicore timeout / HCCL / OOM 系统化排查指南

昇腾 NPU 模型推理运行时错误诊断与修复实战:基于 CANN cann-recipes-infer 的 aicore timeout / HCCL / OOM 系统化排查指南 昇腾 NPU 模型推理运行时错误诊断与修复实战基于 CANN cann-recipes-infer 的 aicore timeout / HCCL / OOM 系统化排查指南【免费下载链接】cann-recipes-infer本项目针对LLM与多模态模型推理业务中的典型模型、加速算法提供基于CANN平台的优化样例项目地址: https://gitcode.com/cann/cann-recipes-infer导读本文是面向昇腾 NPU 的 LLM 与多模态模型推理运行时错误诊断方法论来源于 cann-recipes-infer 仓库的.agents/skills/model-infer-runtime-debug技能并辅以 executor 与 models 目录下的真实实现加以印证。文中系统覆盖 aicore timeout507014、HCCL 通信错误、显存 OOM、Shape 不匹配、算子约束违反以及推理卡住等高频故障给出先定位再修复的二分法排查路径、常见算子约束速查表、四类修复策略与验证清单并区分框架部署与独立部署两种进程模型。读完本文你将能够独立完成 NPU 推理链路上从报错定位到修复验证的全过程并掌握npu-smi 日志 检查点三类工具的组合用法。诊断心法先定位再修复NPU 运行时错误的排查核心是先定位再修复通过二分法逐步缩小故障范围避免在错误方向浪费时间。本文不覆盖精度问题NaN、输出偏差等精度调优请转向仓库中的model-infer-precision-debug技能见 .agents/skills/model-infer-precision-debug/SKILL.md。部署模式适配先确认你在哪条进程模型上诊断流程对框架部署与独立部署两种模式均适用但启动协议、通信组管理、KV cache 接入、权重加载四条链路的差异会直接决定错误的排查方向必须先确认当前部署形态维度框架部署独立部署启动协议executor/scripts/function.sh 中的launch多卡 fork python通过LOCAL_RANK/RANK_ID环境变量区分每个 rank 的进程torchrun --nproc_per_nodeN infer.py由 torchrun 自动注入RANK/WORLD_SIZE/LOCAL_RANK/MASTER_ADDR/MASTER_PORT通信组管理由executor.core.config.comm_manager.CommManager一次性建组模型类通过comm_manager.get_group(name)取组Runner 内 inlineParallelContext对外接口对齐get_group(name)/get_group_name(name)/get_rank(name)KV cache 接入由 executor/core/kv_cache 自动管理cache_entries/block_table[attn_type]/slot_mapping[attn_type]Runner 自管 KV tensor block_tableslot_mapping权重加载enable_online_split_weight: True时由ParallelLinear.weight_loader自动按 rank 切分Runner 自管或调用 executor/model_loader/weight_utils.py 中的default_weight_loader例如出现 HCCL 错误时首先要确认走的是哪条建组路径框架部署应核查CommManager.initialize()传入的group_stride/group_num参数独立部署则应核查ParallelContext.build_parallel_context()内init_comm_group的调用参数。以 executor/core/config/comm_manager.py 为例CommManager对外暴露get_group(name)/get_rank(name)/get_group_name(name)/has_group(name)/register_group(...)五个接口模型通过register_group声明业务通信组由 manager 统一完成子组物化、签名缓存复用与 HCCL 组名捕获——这意味着所有 rank 必须以完全相同的顺序、相同的参数创建通信组任何一条 rank 的参数不一致都会引发 HCCL 建组失败或后续通信死锁。诊断路径总览故障发生后先根据有无明确错误信息分流再按决策树逐级下钻问题发生 │ ├── 有明确错误信息 → 通用诊断流程 │ ├── aicore timeout (507014) → 二分法定位 │ │ ├── 定位到阶段 → 层 → 模块 → 算子 │ │ └── 查表「常见算子约束」→ 修复策略 → 验证 │ ├── OOM → 检查参数量 / batch_size / seq_len / 中间 buffer │ ├── Shape 不匹配 → 检查 TP/EP 切分维度 / Prefill vs Decode 分支 │ └── HCCL timeout → 检查各 rank 代码路径一致性 / 通信组创建 │ └── 无明确错误 → npu-smi 状态检查 ├── 部分 rank 缺失 / HBM 不均 → 多卡部署诊断 │ ├── 权重加载 crash → TP 切分越界 / vocab pad │ ├── Config 字段缺失 → Config 兼容性 │ └── 静默失败 → 逐 rank 检查日志 ├── 有进程 HBM 不变 CPU 100% → 推理卡住诊断 - 模型构造阶段 ├── 有进程 HBM 不变 CPU 0% → 推理卡住诊断 │ ├── 检查残留进程 │ ├── eager 也卡 → syncprint 定位通用流程第二步 │ └── 仅 graph 卡 → 比较 eager/graph 代码路径差异 └── 0 进程 → 查 rank 0 日志 → 通用诊断流程npu-smi 状态检查无报错时的第一现场当没有明确错误信息时先运行npu-smi info读取设备状态用一张表完成初步定性npu-smi 表现含义诊断路径前 N 进程存在后面缺失HBM 不均高位 rank 在权重加载时 crash→ 多卡部署诊断8 进程HBM 均匀AICore 全 0%所有 rank 卡在通信等待→ 推理卡住诊断有进程HBM 不变 ~3GBCPU 100%CPU 密集操作模型构造/权重初始化→ 推理卡住诊断 - 模型构造阶段有进程HBM 不变 ~3GBCPU 0%死锁/通信等待→ 推理卡住诊断8 进程HBM 持续增长权重加载中等待0 进程全部 crash查 rank 0 日志 → 通用诊断流程值得注意的是框架部署的launch_infer_task会为每个 rank 分配 CPU 核心绑定taskset -c且 rank 0 的 stdout 通过tee输出、其余 rank 只写日志文件executor/scripts/function.sh。因此终端无输出并不能代表推理状态必须以npu-smi或日志文件为准。通用诊断流程适用于有明确错误信息的场景aicore timeout、HCCL error、OOM、shape mismatch 等。整体按分类 → 定位 → 查表 → 修复 → 验证线性推进。第一步错误分类拿到错误信息后先判断属于哪一类。不同类别的根因和排查路径完全不同分类错误会浪费大量时间。A. aicore timeout错误码 507014特征AclrtSynchronizeDeviceWithTimeout、error code is 507014、aicore timeout、fftsplus aivector error、Kernel task happen error, retCode0x25。含义某个 NPU 算子在设备上执行时超时未返回。这是最常见也最难排查的错误——因为报错的位置synchronize 调用处通常不是出错的位置某个具体算子。常见根因算子入参违反硬件约束如 A2 上 MC2 要求experts_per_rank 24见下文「常见算子约束」算子 shape 超出硬件限制如单次 matmul 的 M/N/K 维度超限死锁部分 rank 走了不同的通信路径导致集合通信永远等不齐内存越界slot_mapping/block_table索引超出 KV cache 分配范围B. HCCL 通信错误特征HCCL_CONNECT_TIMEOUT、HCCL error、AllReduce/AllToAll timeout、HCCL_EXEC_TIMEOUT。含义分布式通信操作超时或失败。常见根因各 rank 进入通信操作的顺序/次数不一致代码分支导致部分 rank 跳过某次通信常见于 modeling forward 内有if forward_metadata.is_prefill等分支通信组创建时参数错误框架部署核查CommManager.initialize()的group_stride/group_num独立部署核查ParallelContext.build_parallel_context()内init_comm_group调用参数MoE EP 场景缺moe_ep_group_namedispatch_v2/combine_v2算子要求 HCCL group name框架部署用comm_manager.get_group_name(moe_ep_group)独立部署用parallel_ctx.get_group_name(moe_ep_group)。这一点在 models/deepseek_v4/models/modeling_deepseek.py 中有直接体现——MoE 推理会同时声明moe_ep_group供all_to_all_single使用与moe_ep_group_mc2供 dispatch/combine 取 HCCL group name两者缺一不可网络问题跨节点时HCCL_IF_IP配置错误HCCL_BUFFSIZE不足大 batch / 大 hidden_size 的 dispatch/combine 失败——调高至 512MB 试试。仓库中CommManager读取环境变量HCCL_BUFFSIZE默认值为_DEFAULT_HCCL_BUFFSIZE_MB 200executor/core/config/comm_manager.py大模型场景建议显式调大某些 rank 已经 crash 但其他 rank 还在等它参与通信C. OOM显存不足特征NPU out of memory、Tried to allocate X GiB、ENOMEM。含义NPU HBM 不够。常见根因模型参数 / KV cache / activation 总和超过单卡显存中间 tensor 未及时释放常见于 MoE EP all-to-all 中间 bufferbatch_size 或 seq_len 超出预期migrator 阶段单卡 OOM编排层会标记需多卡并行化parallel-impl skill后再补采基线不是必修问题D. Shape 不匹配特征RuntimeError: shape mismatch、expected size X but got Y、mat1 and mat2 shapes cannot be multiplied。含义tensor 维度不对。常见根因TP 切分后维度未正确除以tp_size核对ParallelLinear的tp_size/tp_rank标准做法是用comm_manager.get_rank(attn_tp_group)/parallel_ctx.get_rank(attn_tp_group)等取值避免硬编码KV cache 的num_head字段必须用num_kv_heads_per_rank max(num_kv_heads // attn_tp_size, 1)与 parallel-impl skill 的attn_tp_size改动联动EP 切分后每卡专家数计算错误检查experts_per_rank num_experts // ep_sizemodels/deepseek_v4/models/modeling_deepseek.py 正是按此公式计算Prefill/Decode 分支传入了错误 shape 的 tensor阶段分支统一用forward_metadata.is_prefillpacked sequence 协议错误modeling 内hidden_states被 reshape 成[B, S, H]变长 batch 不能简单 reshape应保持[TotalTokens, hidden_size]二维详见 model-infer-kvcache 技能多 attn_type 混合模型误把block_table当 plain Tensor 传给 FA应该取block_table[self.attn_type]dict 索引E. 算子约束违反特征不直接报约束错误通常表现为 aicore timeout 或 SIGABRT。需要通过二分法定位后查阅算子文档确认。含义NPU 自定义算子对入参有隐含约束数据类型、维度范围、硬件平台限制违反时行为未定义。第二步二分法定位syncbarrier 检查点法这是核心方法。当错误发生在torch.npu.synchronize()时错误信息只告诉你设备上有东西出错了不告诉你具体哪个算子。通过插入检查点逐步缩小范围。关键陷阱NPU 操作是异步的。model.prefill()返回不代表 prefill 完成——只有torch.npu.synchronize()返回才代表所有已提交的操作完成。所以报错位置synchronize 调用处不一定是出错位置某个具体算子。确保检查点覆盖所有可能的异步操作。2.1 定位到阶段Prefill vs Decode在 runner 的model_inference方法中prefill 和 decode 调用之间插入同步检查# 在 prefill 之后、decode 之前 torch.npu.synchronize() logging.info(prefill passed)2.2 定位到层确认出错阶段后如 Decode在每个 decoder layer 之间插入检查点for i, layer in enumerate(self.layers): hidden_states layer(hidden_states, ...) torch.npu.synchronize() logging.info(flayer {i} passed)如果 Layer 0 就超时——问题在第一层内部如果 Layer 2 超时——问题在第 2 层或其子模块。2.3 定位到模块进入出错层在各子模块之间插入检查点# 在 DecoderLayer.forward 中 hidden_states self.input_layernorm(hidden_states) torch.npu.synchronize(); logging.info( norm passed) hidden_states self.self_attn(hidden_states, ...) torch.npu.synchronize(); logging.info( attention passed) hidden_states self.mlp(hidden_states) # MoE torch.npu.synchronize(); logging.info( MoE passed)2.4 定位到算子进入出错模块在每个 NPU 算子调用之间插入检查点。此时通常可以定位到具体算子及其入参结合「常见算子约束」判断根因。2.5 注意事项先用torch.npu.synchronize()做单卡定位确认是哪个算子出错。不要一开始就加dist.barrier()——barrier 会在某 rank 已崩溃时导致其他 rank 永久挂起怀疑多 rank 不同步时用dist.barrier()或torch.distributed.monitored_barrier()确认各 rank 是否走到同一位置。monitored_barrier在超时后会报告哪个 rank 未到达查看所有 rank 的日志确认各 rank 到达的检查点是否一致不一致说明有条件分支差异 → 通信死锁不要一次插入太多检查点——每次 sync 有开销且大量 sync 可能改变时序。先粗粒度再细粒度保留日志把每轮定位的检查点输出保存供后续分析第三步常见 NPU 算子约束速查以下约束来自本仓实际调试经验定位到具体算子后应回到当前调用的 API 签名和官方文档核对不要跨算子套用规则。违反约束的典型表现是 aicore timeout。MoE 相关算子算子约束违反表现解决方案npu_moe_distribute_dispatch_v2(MC2)A2:experts_per_rank moe_expert_num // (ep_world_size - shared_expert_rank_num) 24A3 无此 24 限制aicore timeoutDecode 阶段挂死experts_per_rank 24时回退到 double_routing 路径npu_moe_init_routing_v2 manual all_to_allnpu_moe_distribute_combine_v2(MC2)同上同上同上npu_moe_init_routing_v2无 EP 最小限制但moe_chunk_max_len为 0 可能导致空 tensorSIGABRT 或 shape error设置合理的 moe_chunk_max_len如 1024npu_moe_gating_top_kk不能超过专家总数静默错误输出或 crash检查 reduced model 的 moe_topk 是否已调整以 models/deepseek_v4/models/modeling_deepseek.py 为例可以看到 MoE 推理中存在两条路径npu_moe_distribute_dispatch_v2/npu_moe_distribute_combine_v2MC2 高性能路径与moe_infer_double_routing回退路径走npu_moe_init_routing_v2 手动all_to_all_single。源码中moe_ep_group同时服务于两条路径的集合通信而 MC2 路径额外依赖moe_ep_group_mc2的 HCCL group name——这正是上述约束在真实代码中的落点。FAFlash Attention算子约束说明head_num须匹配实际 Q headsMLA 模型中 head_num num_attention_heads不是 kv_headssparse_modeatten_mask按路径分类标准 LLM TND PA 路径 PrefillDecode 统一 sparse_mode3 causal mask滑窗层统一 sparse_mode4 bandMLA absorb Prefill 3 / Decode 0Noneatten_mask shapesparse_mode3/4时固定[2048, 2048]bool用executor.utils.common_utils.get_init_attn_mask(2048, device)构造input_layout按 API 和阶段区分npu_fusion_attention用 BSH/SBH/BSND/BNSD/TNDnpu_fused_infer_attention_score用复合 layout 如 TND_NTDPA MLA 默认推荐、BSND_NBSDKVP 场景以实际 API 签名为准Decode PA 模式下block_tableshape[batch, max_blocks]值不能超出 cache 分配的 block 数框架部署是Dict[attn_type → Tensor]attention 内取block_table[self.attn_type]FA v1 BSH Q_S1 Decode 算子级限制op 内部忽略sparse_mode/pre_tokens实测 sparse_mode 0 vs 4 等价滑窗模型长序列正确性靠模型层actual_seq_lengths_kv截断NZ 格式 cache需要torch_npu.npu_format_cast转换且 hidden_dim 须为 16 的整数倍关于actual_seq_lengths参数要以当前调用算子的签名与官方 API 文档为准不跨算子套用规则torch_npu.npu_fused_infer_attention_score/torch_npu.npu_fusion_attentionactual_seq_lengths*为List[int]文档为 int64 语义torch_npu.npu_kv_quant_sparse_flash_attentionactual_seq_lengths_query/kv为Tensor文档为 int32仓库中get_init_attn_mask的实现位于 executor/utils/common_utils.py它基于torch.tril生成上三角掩码并支持valid_len参数可直接用于构造 FA 所需的[2048, 2048]bool 掩码。通信算子约束说明all_to_all_single的 split sizesinput_splits 和 output_splits 之和须分别等于 input 和 output 的第 0 维通信组内所有 rank 须同时到达任何条件分支差异都可能导致部分 rank 跳过通信 → 死锁HCCL group 创建顺序所有 rank 须以相同顺序创建相同的通信组第四步修复策略模式定位根因后从以下四类模式中选择合适的修复策略。模式 1算子回退Operator Fallback——当某个高性能算子在当前硬件/配置下不可用时回退到功能等价但限制更少的替代算子# 示例A2 上 experts_per_rank 24 时 MC2 算子不可用回退到 double_routing def forward(self, hidden_states, is_prefill): topk_indices, topk_weights, _ self.router(hidden_states) if is_prefill: return self.moe_infer_double_routing(hidden_states, topk_indices, topk_weights) else: experts_per_rank self.num_experts // (self.moe_ep_size - self.shared_expert_rank_num) if experts_per_rank 24: # A2 MC2 dispatch_v2/combine_v2 requires experts_per_rank 24; fall back return self.moe_infer_double_routing(hidden_states, topk_indices, topk_weights) return self.moe_infer_dispatch_combine(hidden_states, topk_indices, topk_weights)适用场景硬件约束、EP/TP size 不满足算子要求注意回退通常有性能损失需记录在优化报告中模式 2参数修正Parameter Fix——算子入参计算错误如 FAhead_num用了 KV heads 而非 Q heads、TP 切分后维度未除以 tp_size。定位到具体算子后逐个核对入参与算子文档/参考模型的差异。适用场景shape 不匹配、dtype 错误、维度计算错误模式 3路径统一Path Unification——部分 rank 走不同代码路径导致通信死锁# 错误不同 rank 可能在不同 step 进入 prefill/decode if is_prefill: self.all_reduce(...) # rank 0 执行 # rank 1 已进入 decode不执行 all_reduce → 死锁 # 修复确保所有 rank 同步状态后再分支 dist.barrier() is_prefill_tensor torch.tensor([int(is_prefill)], devicenpu) dist.broadcast(is_prefill_tensor, src0) is_prefill bool(is_prefill_tensor.item())适用场景多 rank 死锁、HCCL timeout模式 4配置降级Configuration Downgrade——配置组合不兼容时调整 YAML 参数如降低moe_chunk_max_len、减小batch_size。适用场景OOM、性能异常第五步验证清单修复后按以下清单逐项验证单步验证在出错位置前后加 syncbarrier确认不再超时全流程验证移除所有调试检查点运行完整 warmup inference全 rank 验证检查所有 rank 的日志确认全部成功grep model run success log_*.log输出一致性各 rank 的最终输出应一致对 DP 模式同 DP group 内的 rank 输出应一致性能记录记录修复后的 Prefill/Decode 耗时与修复前对比回退文档如果使用了算子回退记录性能影响和未来可恢复条件特定场景诊断以下场景有独立的诊断路径不走通用流程。通过入口 npu-smi 表判断后直接跳转。多卡部署诊断多卡部署引入了一类单卡不存在的问题权重加载切分、vocab 对齐、部分 rank 崩溃、config 兼容性。共同特点部分 rank 成功、部分 rank 失败错误出现在权重加载阶段而非 forward 阶段。启动协议区分框架部署用executor/scripts/function.sh::launch多卡 fork python每个 rank 单独起进程通过LOCAL_RANK/RANK_ID环境变量区分独立部署用torchrun --nproc_per_nodeN infer.pytorchrun 自动注入 RANK / WORLD_SIZE / LOCAL_RANK / MASTER_ADDR / MASTER_PORT。卡住 / crash 时先确认对应启动方式的进程模型。权重加载 TP 切分越界典型错误RuntimeError: start (105984) length (35328) exceeds dimension size (131125)或ValueError: 131125 is not divisible by 8根因ColumnParallelLinear/VocabParallelEmbedding将权重沿 output 维度切分为对应*_tp_size份。如果 checkpoint 的实际维度不等于模型参数的维度或者不能被对应*_tp_size整除高位 rank 的narrow()操作就会越界。仓库中的 executor/model_loader/weight_utils.pydefault_weight_loader会在param.size() ! loaded_weight.size()时抛出ValueError并打印default weight load failed日志这正是此类错误的落点之一。常见场景场景说明修复多模态模型文本推理embed_tokens用 full vocab (282624) 但lm_head用 textspecial (131125)两者维度不同lm_head 单独使用text_vocab_plus_multimodal_special_token_sizevocab 不整除 lmhead_tp_size131125 % 8 ≠ 0向上 pad 到最近的lmhead_tp_size倍数padded ((raw lm_tp - 1) // lm_tp) * lm_tppadded 参数 vs 原始 checkpoint模型参数 131128padded但 checkpoint 权重只有 131125加载时先 pad checkpoint weight 再传给 weight_loader修复模板vocab pad weight pad# 1. 创建 lm_head 时 pad vocab size注意切分用的 lmhead_tp_size 与 attn_tp_size 可能不同 lm_head_raw getattr(config, text_vocab_plus_multimodal_special_token_size, config.vocab_size) self.lm_head_vocab_size ((lm_head_raw lmhead_tp_size - 1) // lmhead_tp_size) * lmhead_tp_size # 2. 加载权重时 pad checkpoint tensor if lm_head in name and loaded_weight.shape[0] self.lm_head_vocab_size: padded torch.zeros(self.lm_head_vocab_size, *loaded_weight.shape[1:], dtypeloaded_weight.dtype, deviceloaded_weight.device) padded[:loaded_weight.shape[0]] loaded_weight loaded_weight padded排查技巧如果只有高位 rank (rank 3-7) crash 而低位 rank (0-2) 正常几乎一定是切分越界——因为低位 rank 的start_idx还在合法范围内。Config 兼容性问题从 HuggingFace 原始模型加载时config.json 可能缺少代码期望的字段或字段格式不同。问题表现修复缺少rope_parametersTypeError: NoneType object is not subscriptableat RotaryEmbedding initConfig__init__中当rope_parametersNone时构造 default{rope_type: default, rope_theta: self.rope_theta}vocab_size含多模态 tokenEmbedding 过大 / lm_head 维度不匹配区分vocab_sizeembedding 用和text_vocab_plus_multimodal_special_token_sizelm_head 用num_hidden_layers歧义Dual-sublayer 架构下 HF 可能存 28attention 层数但物理层只有 14用 property 覆盖property num_hidden_layers - return self.num_layersauto_map指向原始模型代码加载时尝试 import 原始 modeling 文件传入自定义 config class 到from_pretrained最佳实践在 config class 的__init__末尾为缺失字段补 defensive defaults。对有模型差异的参数如rope_theta从 config.json 读取而非硬编码默认值缺失时报错。部分 Rank 静默失败有时 rank crash 了但错误被吞掉存活的 rank 卡在下一个dist.barrier()或集合通信上看起来像推理卡住。诊断流程# 1. npu-smi 确认进程数 npu-smi info | grep Process id # 2. 逐 rank 检查日志末尾 for i in $(seq 0 7); do echo Rank $i tail -5 logs/log_${i}.log done # 3. 检查是否所有 rank 都到达了同一个里程碑 grep model run success logs/log_*.log # 或 grep Loading weights took logs/log_*.log多卡权重加载检查清单在发起多卡推理前逐项确认embed_tokens 维度checkpoint 里 embed_tokens.weight.shape[0] 和 config.vocab_size 一致lm_head 维度checkpoint 里 lm_head.weight.shape[0] 可能小于 embed_tokens多模态模型常见*vocab 整除对应_tp_sizelm_head 和 embed_tokens 的 output_size 都能被各自lmhead_tp_size/embed_tp_size整除不能则 padper-rank head 数attn_tp_size 改动后num_kv_heads_per_rank max(num_kv_heads // attn_tp_size, 1)cache_entries.num_head 字段同步更新ignore 规则覆盖_keys_to_ignore_on_load_unexpected包含所有不需要的权重前缀ngram、visual、audio、mtp 等config 字段完整rope_parameters、num_layers、zero_expert_num等代码必需字段在 config.json 中有或有 default模型路径绝对路径相对路径可能在不同 rank 的 cwd 下解析不同enable_online_split_weight 与 weight_loader 实现YAML 设 True 时 ParallelLinear / FusedMoEGMM 的 weight_loader 必须正确处理 tp_rank / ep_rank 切分推理卡住诊断推理卡住与 crash 不同——进程仍在运行但不产出结果。需要区分真卡住和假卡住。先通过入口 npu-smi 表判断状态再按以下路径排查。eager 模式复现卡住 → 换 eager YAML 跑同样模型 ├── eager 也卡 → bug 在模型代码 → 用 syncprint 定位 ├── eager 正常 → bug 在图模式适配 │ ├── 看报错ERR03007 / graph break → 找不兼容的算子 │ └── 无报错但慢/卡 → 比较 eager 和 graph 模式代码路径差异 └── 两者都正常但上次卡了 → 检查是否有残留进程占 NPU模型构造阶段卡住CPU 密集症状日志停在 HCCL init 之后HBM 不增长但 CPU 100%。原因机制修复nn.Embedding大 vocab 初始化大 vocab 的nn.Embedding用normal_()填充随机值多个 embedding 累计耗时可达数分钟用no_init_weights()上下文包裹跳过将被 checkpoint 覆盖的参数初始化VocabParallelEmbedding瞬态内存继承nn.Embeddingsuper().__init__(full_vocab, dim)先创建全 vocab tensor再用 per-partition tensor 替换瞬态 CPU 内存远超最终占用用nn.Moduletorch.empty(per_partition_size)直接创建 per-partition 权重避免瞬态全 vocab 分配post_init()遍历所有参数HuggingFacePreTrainedModel.post_init()调用_init_weights对每个参数做初始化大模型参数量多时很慢对从 checkpoint 加载的大参数模块用no_init_weights()跳过诊断技巧# 区分真卡和 CPU 密集慢 ps aux | grep infer.py | awk {print $2, $3%CPU, int($6/1024)MB} # CPU 100% 还在算慢但没死 # CPU 0% 真卡住等通信/IO修复模板大 embedding 模块from transformers.modeling_utils import no_init_weights # 用 no_init_weights 包裹避免对即将被 checkpoint 覆盖的参数做随机初始化 with no_init_weights(): self.large_embeddings LargeEmbeddingModule(config, ...)残留进程导致 HCCL 卡住症状新启动的推理卡在 HCCL init不报错不超时。根因上次推理的进程未正确退出仍占用 NPU 设备或 HCCL 端口。修复# 1. 杀死残留进程 ps aux | grep infer.py | grep -v grep | awk {print $2} | xargs kill -9 # 2. 等待 NPU 释放 sleep 3 # 3. 确认 NPU 完全空闲 npu-smi info | grep No running # 期望输出 8 行 No running processes found # 4. 重新启动推理预防每次启动推理前先检查并清理残留进程。实际上框架部署的启动脚本本身就内置了这一防护——executor/scripts/function.sh 的check_launch会在启动前用pgrep/ps检测是否已有infer.py/server.py进程在运行若有则直接中断并提示script was interrupted and exited从源头避免残留进程导致的 HCCL 卡住。附录运行监控与提效以下命令示例基于当前仓默认的日志路径和启动脚本约定executor 或日志组织变更后需相应调整。核心原则判断完成状态看进程不看日志流。多卡推理通过infer.sh后台启动 N 个进程再wait。rank 0 的 stdout 通过tee到终端可能缓冲截断其他 rank 只写日志文件见 executor/scripts/function.sh 中tee与的分流处理。完成检测方法方法命令说明查 NPU 进程npu-smi info \| grep running process无进程 已结束查非 rank0 日志grep model run success logs/*/log_1.logRank 1-7 日志不经 tee完整写入。不要只查 rank 0查所有 rankfor i in $(seq 0 7); do grep -l model run success logs/*/log_${i}.log; done \| wc -l期望输出 world_size日志关键字判断阶段grep Loading safetensors logs/*/log_1.log # 正在加载权重 grep Loading weights took logs/*/log_1.log # 加载完成 grep inference time cost of prefill logs/*/log_1.log # 推理已开始 grep model run success logs/*/log_1.log # 推理已结束这些关键字与仓库实际日志输出一一对应例如 executor/utils/common_utils.py 中的obtain_mtp_stats会打印Finished inference, number of loop step is ...与模型平均推理耗时executor/utils/common_utils.py 的detokenize_outputs会打印 Inference decode result 输出。一条命令获取全局状态echo NPU npu-smi info | grep -E Process|HBM | head -5 \ echo Log tail -3 logs/*/log_1.log \ echo Done? grep -c model run success logs/*/log_*.log 2/dev/null常见误判场景现象原因正确做法终端无新输出以为在运行Rank 0 的 tee 管道已关闭或缓冲未刷查npu-smi或查 rank 1-7 日志Rank 0 日志没有 model run successtee 截断查 rank 1 的日志sleep 120后还没完成模型大/首次编译慢先npu-smi判断存活再看 HBM 变化判断阶段grep 日志找不到关键字进程 crash 了没写 success查npu-smi确认进程不在 → 查tail -20 log_*.log看错误Agent 工作模式启动推理bash infer.sh前台或run_in_background不要盲目 sleep——用run_in_background等通知或前台直接看输出10 分钟无进展 → 主动排查推理启动超过 10 分钟仍无model run success输出不要继续等待按「推理卡住诊断」流程排查npu-smi→ 判断状态 → 分流超时后第一步查npu-smi不要先查日志检查完成时查 rank 1不是 rank 0——rank 1 日志完整无截断一次检查多个信号npu-smitail log_1.loggrep model run success log_*.log并行执行总结NPU 推理运行时错误的排查本质是一场缩小范围的游戏先用npu-smi定性crash / 卡住 / 通信等待再用torch.npu.synchronize()检查点二分定位到具体算子随后对照算子约束速查表确认根因最后从四类修复模式中选择策略并完成六项验证。仓库中的 .agents/skills/model-infer-runtime-debug/SKILL.md 将这套方法论沉淀为可复用的 Agent 技能配合 executor/core/config/comm_manager.py通信组管理、executor/scripts/function.sh启动协议与残留进程防护、executor/model_loader/weight_utils.py权重加载以及 models/deepseek_v4/models/modeling_deepseek.pyMoE 算子路径与回退等源码实现开发者可以在实际故障面前快速定位根因、完成修复并形成可复用的排查经验。【免费下载链接】cann-recipes-infer本项目针对LLM与多模态模型推理业务中的典型模型、加速算法提供基于CANN平台的优化样例项目地址: https://gitcode.com/cann/cann-recipes-infer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表