基于VeRL框架在Atlas 800T A2上打通DeepSeek-671B DAPO强化学习训练流程实践

基于VeRL框架在Atlas 800T A2上打通DeepSeek-671B DAPO强化学习训练流程实践 ​作者​昇腾实战派​知识地图​https://blog.csdn.net/Lumos_Lovegood/article/details/161601003背景概述在大模型强化学习训练中DeepSeek-671B模型因其参数量巨大、结构复杂含MLA、MoE等对推理和训练框架的适配提出了极高要求。本文基于VeRL开源强化学习仓库在Atlas 800T A2集群上完成了DeepSeek-671B-R1-Zero的DAPO强化学习训练流程打通解决了推理乱码、显存溢出、精度对齐等关键问题最终实现了端到端性能达标。本文从适配方案、流程优化、问题定位与解决等角度进行技术总结为后续DeepSeek系列模型的强化学习训练提供前置技术路线。关键里程碑在Atlas 800T A2集群上基于VeRL开源仓库打通Deepseek-671B-R1-Zero DAPO强化学习训练流程完成关键指标reward与response length曲线对齐最终Atlas 800T A2上端到端性能达到预期指标。功能适配方案选择推理引擎目前VeRL支持的推理引擎有vLLM和SGLang两类。其中vLLM的适配工作较多当前昇腾有基于vLLM-Ascend在Qwen2.5、Qwen3等模型上完成强化学习相关适配工作的成果和经验因此以vLLM/vLLM-Ascend为推理引擎做新模型的适配。训练后端由于DeepSeek-671B模型参数较为庞大FSDP后端无法承载该规模尺寸的模型训练因此首选Megatron进行训练后端的适配且目前MegatronMindSpeed已有成熟经验。框架开发当前VeRL社区代码未支持DeepSeek-671B模型训练无基线数据。打通流程VeRL强化学习框架由推理和训练两部分组成当前DAPO训练策略采用训推全共卡方案即推理引擎和训练后端以分时复用方式共享显存。训练通常需要占用大量计算资源而推理依赖于训练模型但其decode阶段耗时较长导致训练需要等待推理完成存在大量闲置等待时间整体适配效率较低。在传统的功能打通流程中推理和训练是串行进行的通常需要先打通推理再打通训练。然而在实际打通推理功能时并不需要实际用到训练模型因此无需占用大量计算资源。同时由于推理和训练的交互本质上是推理结果的传递这种串行流程导致了大量计算资源的浪费和调试闲置时间进一步降低了开发和适配效率。真实训练打通过程中我们提出可以通过打桩生成推理结果将推理和训练的功能适配工作解耦并行化开展推理和训练的功能打通工作。这样无需等待实际推理完成即可同时进行训练的功能验证和调试避免资源闲置和等待时间从而显著降低物料浪费提高适配效率其流程如下图所示。请添加图片描述打通实践针对671B大规模模型在有限的适配时间下我们采用推理、训练阶段并行大模型减层从单机到多机再到满层拉起的策略具体方案如下并为大家介绍其中关键环节。环境准备基础环境配置项版本信息AI服务器Atlas 800T A2 64G驱动、固件24.1.0.3Python3.10.12CANN8.2.RC2torch2.7.1torch_npu2.7.1transformer4.53.3vllm0.10.0vllm-ascend0.10.0rc1verl0.7.0.dev0Megatron-core0.12.1MindSpeed2.2.0_core_r0.12.1Mbridge0.13.1FP8转BF16权重DeepSeek V3模型原生采用FP8混合精度训练需转为BF16权重。原生fp8_cast_bf16文件基于Triton算子优化使用可能会存在一些问题现提供NPU已打通的fp8_cast_bf16.py文件fp8_cast_bf16.py基于VeRL场景下的K8s任务使能该项目场景是基于K8s裸机生产集群拉起强化学习任务此场景下无法直接获取全部节点IP只能通过K8s调度工作相较常规开发环境存在差异。现提供常规的执行脚本如下任务拉起可通过K8s命令启动对应YAML文件。https://gitcode.com/Ascend/mindcluster-deploy/blob/master/samples/train/resumable-training/fault-tolerance/without-ranktable/pytorch/verl/verl-resche.yaml三方组件MbridgeMbridge是一个提供HF权重与MCore权重在线自动转换的工具支持在线的权重导入及导出不需要依赖离线保存的MCore权重并且支持TP/PP/CP/VPP/EP/ETP等并行策略。GPU侧基于Mbridge进行了训推权重转换为了保证配置对齐需进行Mbridge在NPU上的功能打通。Mbridge与use_dist_ckpt加载权重的区别Mbridge加载与导出权重的核心代码都在mbridge/core/bridge.py中不需要离线保存的MCore权重直接通过bridge.py中的代码进行在线权重转换。use_dist_ckpt加载权重的代码内置在VeRL的Megatron Workerverl/workers/megatron_workers.py中训练过程中按切分加载提前保存好的离线MCore权重。适配方式Mbridge安装略NPU适配手动在Mbridge读取safetensors入口处修改device为NPU具体代码路径为mbridge/models/ext/deepseek_v3/dequant_fp8_safetensor_io.py如下图所示使能Mbridge功能VeRL中配置了Mbridge使能的参数开启该配置并关闭dist加载权重配置即可开启Mbridge具体配置如下推理EP使能DeepSeek满血版模型因参数量级高带来推理阶段的资源开销过高而现有资源有限因此在VeRL强化学习场景启用推理阶段的专家并行EP机制。为使能推理EP我们增加核心环境初始化逻辑为每个分组配置独立的通信主节点完成VLLM分布式通信环境变量的注入。代码修改位置verl/workers/rollout/vllm_rollout/vllm_rollout_spmd.py关键代码如下Skip_rollout使能Skip_rollout功能是指将VeRL强化学习过程中的推理结果保存下来在之后的所有训练流程中都跳过推理部分直接进入到训练。这在大GBS、长序列的场景中往往可以将推理耗时2~12小时缩减到5分钟。使能方式如下该功能的v1版本已经上仓VeRL可通过添加对应参数使能。通过该功能我们可以在指定路径上dump一次推理的数据并在之后自动获取缓存信息跳过推理阶段直接进行训练阶段调试。单推代码单推功能是模拟VeRL场景下单独拉起vLLM离线纯模型推理的代码贴合实际使用场景包含Ray集群初始化、VLLM推理引擎构建、适配TP/EP切分策略重写VeRL场景下的generate_sequences等方法但仅完成推理阶段并会打印部分推理信息轻量测试强化学习推理阶段功能。相关代码如链接所示https://gitcode.com/Ascend/msit/pull/4766脚本拉下来单独运行需要VeRL作为环境依赖。使能方法单机减层测试结果减层吐字乱码仅做功能打通示例训练阶段MLA使能MLAMulti-head Latent Attention是由DeepSeek团队提出的多头潜注意力优化机制。与传统KV Cache不同MLA并不直接存储完整的Key和Value矩阵而是通过一个压缩隐向量来表示Key和Value借助低秩压缩技术降低KV Cache。在训练中Query也会进行低秩压缩以降低激活值内存。强化学习场景下NPU基于MindSpeed后端使能MLA方法如下其余详细参数可见特性说明文档https://gitcode.com/Ascend/MindSpeed/blob/2.2.0_core_r0.12.1/docs/features/multi-head-latent-attention.md断点续训大模型断点续训是指在模型训练过程中如因硬件故障、网络中断、资源调度或主动暂停等原因终止后能够基于训练中断时保存的完整状态包括模型权重、优化器参数、学习率调度器状态、数据加载进度、训练迭代次数等核心信息直接恢复至中断节点继续训练的能力无需从头重启整个训练流程在问题定位和长稳训练中起着关键作用。VeRL框架权重保存及断点续训关键参数如下其中resume_mode参数包含三个可选值其意义如下VeRL框架本身支持断点续训但在实践中我们发现基于特定场景下断点续训涉及的权重保存和加载存在问题。权重保存当采用Mbridge进行训练保存权重时VeRL代码会保存HF Model走入Mbridge的save_hf_weights()权重保存逻辑。权重保存关键代码mbridge/core/safetensor_io.pyfilename_to_keys_map作为model.safetensors.index.json文件的映射文件以Moonlight-16B-A3B模型文件举例filenamesafetensors文件名keys_for_file包含所有相同safetensors文件的keys列表states遍历生成器获取的权重keys和对应的tensor张量判断逻辑遍历生成器获取权重当states字典存储足够多的权重使得每个keys_for_file作为states.keys()的子集即可保存对应safetensors文件。只要对应的模型权重不符合条件存在缺失权重就无法保存对应文件。问题案例MoonLight-16B-A3B模型权重几乎与DeepSeek模型结构一致在后期资源不足的情况下我们将基于MoonLight-16B-A3B进行验证断点续训也是如此。在使用Mbridge组件下我们观测到对应HF Model并未保存。问题根因遍历训后的模型权重发现MoonLight-16B-A3B模型的model.safetensors.index.json文件存在self_attn.rotary_emb.inv_freq层但该层并未参与训练后续生成器获取的权重没有对应key-value值所以导致每次判断逻辑都无法满足要求致使权重保存失败。通过如下修改后即可完整保存权重注意1权重保存采用子集判断逻辑所以一旦模型训后获取的权重存在些许偏差都可能导致模型权重保存失败这里提供Mbridge权重保存经验希望后续其他场景相关问题可以提供相应思路。2DeepSeek模型本身不存在self_attn.rotary_emb.inv_freq层所以通过Mbridge权重保存不会遇到这个问题。权重加载问题现象基于Mbridge权重加载方式下同步使能optimizer_cpu_offload显存优化特性在断点续训阶段出现报错KeyError: master_param。问题根因VeRL在使用Mbridge且进行续训的时候在分布式场景下加载Checkpoint时优化器的shared_state_dict方法未正确区分对应场景导致优化器分片状态解析错误Checkpoint反序列化失败。解决方案1社区修复方案https://github.com/volcengine/verl/pull/38502社区修复方案涉及import transformer_engine当前版本针对import transformer_engine修复。显存问题时间线我们有两个用例用例1: GBS32用例2: GBS128。前期在用例1上OOM频发初始怀疑存在显存释放不干净的情况于是进行显存建模估算以及采集Profiling进行确认首先明确了引发OOM问题的不是因为VeRL框架在NPU上存在显存释放不干净而是推理长度过长导致的。此时查看rollout结果与response length mean指标发现推理长度基本拉满到了12k基本能判断OOM问题是因为推理乱码长序列引发的。中期确认OOM是一个和精度的耦合问题当推理长度很长时OOM不可避免可以明确推理长度很长也确实是模型训崩导致的。后期解决了模型训练的精度问题之前的过长response导致OOM问题不再出现用例2出现大GBS导致的推理OOM问题通过前期的经验快速找到了显存的优化策略。怀疑OOM是由VeRL框架在NPU上存在显存释放不干净引发的需要两步走一是进行显存建模二是采集显存Profiling加以确认框架侧是否存在显存卸载不干净的情况。显存建模模型参数训练切分策略为TP8 PP16 EP16 ETP1first_pp3 layers,last_pp2 layers,middle_pp4 layers。以下得到总的未经过PP切分的静态显存接下来是每个PP内的静态显存[7, 8 x 6, 6]首尾两个PP注意还有word_embedding与output_layer。推理切分策略为TP8 EP64。Dense部分与训练一致但是在MoE层上不再被ETP切分而是被TP切分则静态显存为以上讨论了静态显存逻辑在update阶段还有激活显存总激活也相当于第一个PP stage micro batch激活Dense * 3 MoE * 58 loss 0.15435791 * 3 0.578186035 * 58 0.246582031 34.2444458(GB)训练开启全重计算仅保留embedding后的激活 [s/TP, b, h] 为0.006835938 GB与loss部分的激活0.246582031 GB加和为0.253417969 GB即只考虑0.2534GB的激活。算上首PP静态显存其总的显存占用为33GB左右。VeRL显存Profiling采集首先明确HybridEngine下卡上显存的占用逻辑采集显存Profiling进行分析拿到总体显存变化趋势符合预期占用逻辑。第一个step拿出各阶段的显存情况结合Timeline侧打出的显存情况vLLM推理引擎侧分析sleep模式是否生效此处能观察到显存有一段回落结合Timeline分析此处是完成了vLLM推理结合代码调用情况vLLM在结束推理后会调用release操作即进入sleep模式此时会根据sleep level进行param与kv cache的释放主要的机制就是unmap_and_release中的aclrtFreePhysical该操作会对指定的tag进行处理比如weights然后会offload到CPU侧。看具体代码执行这部分在vLLM-Ascend中的CaMemAllocator中进行管理。结合显存曲线变化及时间点切入在app reserved即进程保留一线上符合预期做完release操作后为将分配allocated较reserved超出的部分回收一般都会进行empty_cache的操作但是此处发现了一个问题app reserved曲线一般都会较op侧allocated与reserved的高此处看到两条op相关的曲线在做完generate_sequence操作后与app reserved曲线发生偏离并较之高基本认定是vLLM自行管理的aclrtFreePhysical在torch侧是感知不到的。Profiling显存进一步分析拆解npu_module_mem.csv文件大致主要分为APP、HCCL、Runtime三个部分其中HCCL占用了6-8GB这个也暂时先进行记录看后续能否通过HCCL_BUFFSIZE设置再进行一些控制。通过挖取npu_module_mem.csv文件中显存占比大头主要发现两部分APP与HCCL占用单拎出来进行分析如前文所述APP侧进程主要包括shardingrollout、old_logp、ref_logp、update四个阶段在状态切换的时候明显可以看到显存基本释放为0了。而在Profiling曲线中呈现的不归零的情况主要是由HCCL侧导致的显存大小HCCL侧曲线基本在6-8GB两部分一叠加就形成了Profiling APP reserved曲线中的不归零的情况。上述过程从理论建模到实际采集显存Profiling从推理引擎分析到整体曲线说明基本能得出在2k-2k的短序列场景下模型不会出现OOM的情况。但是注意到在VeRL中最后计算logits时会存在[b,s,v]的shape我们可以简单计算下在2k推12k且因为精度乱码的情况下在rollout后的训练阶段会有多大的显存压力RL训练开了dynamic batch_size那么batch会被算法装箱从而micro_batch的大小会做调整默认值设置的是2通过装箱操作后其大小会改变此处以5做举例[5, 1024 x 14, 1024 x 128]1024 x 14是2k推12k全部推满的序列的长度1024 x 128是模型词表的长度logits按照4byte来计算显存大小为4 x 5 x 1024 x 14 x 1024 x 128 / 1024^3 35GB长序列场景下基本就是显存爆炸的状态。actor阶段需要的显存约为35G 8GHCCL 37G模型权重 80G。所以本质上要解决2k推12k的显存问题还是得从解决精度问题的角度出发先保证模型不会每次都推满到12k至于在模型正常推满到12k还出现OOM问题时此处可通过开启CP进行缓解。分析完显存问题后接下来本文将重点分析VeRL 671B精度问题探究reward曲线怎么一步步通过修复问题与GPU基线对齐。大batch下Prefill阶段在推理的MLA处OOM问题GBS128 dynamic bsz PP16 关闭overlong 2e-6 lr做该组配置实验时候遇到的问题Prefill阶段在MLA处发生了OOM的情况。分析加大GBS后原本[b,1,1,s]的attn_mask显存申请加大当与attn_weights进行加和时shape也会进行相应的shape广播从而在此处会形成显存OOM的情况。解决方式问题出在MLA prefill阶段走的是vanilla分支实现为小算子实现通过开启chunk_prefill_for_mla走到融合算子中可避免此情况的发生。精度问题问题梳理精度问题表现为功能打通后启动的DeepSeek 671B-Base模型DAPO训练其reward曲线未能与GPU对齐。后续通过对齐代码版本、对齐拉起脚本、升级VLLM版本以及PTA版本、适配差异化功能等手段最终基于两份setting对齐了reward曲线。同时进行了消融实验定位到三个主要影响到精度的差异点。精度问题的闭环历时一个月其时间线如下精度问题主要有2个阶段的表现整网功能验证阶段无标杆的推理精度问题使用Instruct模型当推理load_formatdummy时rollout输出为乱码可以通过load_formatsafetensors规避。整网长跑比对阶段有GPU基线的训练精度问题使用Base模型rollout结果和GPU近似但长跑reward曲线上升速度低于GPU。精度问题1load_format dummy 推理乱码问题分析在VeRL强化学习场景下由于推理的权重来自于训练actor因此理应无需关心初始化推理时模型的加载方式。但实验发现如果vLLM的load_format为dummy即随机初始化则NPU侧的推理始终为乱码但GPU能够正常推理。VeRL首次推理前的权重情况图解如图所示VeRL先做训练模型的初始化然后做推理模型的初始化。在训推模型初始化后会自动抛弃掉vLLM的权重sleep_mode2其后VeRL会将训练模型的权重sharding到推理模型中即推理模型的权重始终会被训练部分的权重覆盖。无论load_format是dummy还是safetensors其推理都不应当是乱码。在功能打通阶段时该问题通过加载safetensors暂时规避由于后续训练出现精度问题该处作为疑点之一需要深入正向定位。定位思路由于社区上没有已知的相关Issue且GPU功能正常因此主要差异点应当在NPU和GPU的实现上由于当下没有足够多的GPU资源拉起DeepSeek-671B因此需要基于DeepSeek和其他模型的差异点找到可以小规模问题复现的场景。在可以复现的场景上首先对比load_format为safetensors和dummy两者sharding后的权重内容如果权重一致则对比两者的推理前向是否一致找到差异点后追溯根因。模型结构解析DeepSeek在推理方面与其他模型的区别在于①总共61层的Decoder前3层为Dense结构后58层为MoE结构②Decoder的attn为MLAMulti-Head Latent Attention。以小见大由于VeRL更新较快需要在其他模型上验证当前VeRL的版本能力。1在成熟模型Qwen3上尝试复现尝试在Qwen3-30BMoE上进行复现load_format为dummy时推理正常。尝试在Qwen3-32BDense上进行复现load_format为dummy时推理正常。Qwen3的两个成熟用例可以正常运行这说明当前的VeRL代码的load_formatdummy能力是具备的。2在类DeepSeek的Moonlight-16B模型上复现Moonshot-Moonlight 16B-A3B模型是一个类DeepSeek的模型和DeepSeek一样存在Dense、MoE混合部分是一个非常适合用以验证的模型。参数名称DeepSeekV2MoonlightarchitecturesDeepseekV3ForCausalLMDeepseekV3ForCausalLM参数量671B16B层级61层27层旋转编码yarnDeepseekScalingRotaryEmbeddingbase混合MoE/Dense前3层前1层注意力类型MLAMLA由于当前的vllm/vllm-ascend暂未有适配moonlight的经验因此需要在短时间内快速穿刺打通该模型。在该打通过程中又遇到了易用性问题Moonlight包含有MLA模块这一模块实际上调用到的是被vllm-ascend的MLAnpu。MLAnpu在代码实现上默认了rope的类型是DeepseekScalingRotaryEmbedding但由于moonlight的rope是原始的旋转编码因此出现了相关报错。如图所示为临时修复方案当rope方式不为DeepseekScalingRotaryEmbedding则按照原始的rope方式获取对应的cos_cache和sin_cache。实验证明该模型复现了DeepSeek相同的现象即推理load_formatdummy时会存在乱码。3) 在Moonlight模型上对比权重首先判断权重是否正常sharding通过在对应位置添加代码进行落盘对比。具体落盘位置采用的落盘方法通过落盘后对比权重统计如下表所示的结果。两边的所有权重都相同标记为✅否则标记为❌。dummysafetensors是否一致init①sharding beforedummyinit①sharding before✅②sharding after❌❌safetensorsinit❌❌①sharding before❌❌✅②sharding after❌❌✅权重的落盘对比结果符合预期对于dummy和safetensors模型初始化init和模型同步前sharding before的内容都相同dummy格式的init权重和safetensors的init权重不一致dummy格式的sharding after权重和safetensors格式的sharding after权重相同。确认完权重部分正常需要进一步做前向推理比对来继续定位。4在Moonlight模型上对比推理前向通过对mooonlight推理中所有的forward部分进行打桩记录所有的输入输出并在safetensors和dummy进行对比。对比结果mla-attn模块 layer 0层 输入一致输出不一致。进而导致后续的所有层都对不齐因此定位到mla-attn层的差异。进一步定位发现出现前向不一致的位置在于vllm-ascend中MLA模块的_v_up_proj方法。debug到对应的位置进行逐行对比可以看到两边的self.W_UV和self.W_UK_T无法对齐。根因定位1找到W_UV、W_UK_T的赋值位置既然这两个矩阵在NPU上的值和GPU对不上那顺藤摸瓜得看看这两个变量是怎么赋值的。具体位置在vllm_ascend\attention\mla_v1.py: 650在这里打了断点确定整网导致在什么时候调用到了这里首次初始化模型的时候调用过process_weights_after_loading()函数模型在verl中初始化 对vllm的 LLM实例化的时候首次进入 process_weights_after_loading 之后不再进入MLA 层会初始化这两个变量用于前向计算首次被赋值。如果load_formatdummyGPU和NPU这里都是随机权重但之后再也没有调用过这里为什么GPU的推理时正常的但NPU的推理是乱码已经找到了W_UV和 W_UK_T的赋值位置接下来在前向计算的时候继续定位GPU和NPU的差异。2vLLM MLA-attn 权重更新差异分析再次通过落盘对比在下图做前向的位置打断点GPU第 1 步的 kv_b_proj和第2步的 kv_b_proj 是同一片地址空间且落盘对比一致第1步的W_UV和 W_UK_T与第2步的W_UV和 W_UK_T是同一片地址空间落盘数值存在差异。NPU第 1 步的 kv_b_proj和第2步的 kv_b_proj 是同一片地址空间且落盘对比一致第1步的W_UV和 W_UK_T与第2步的W_UV和 W_UK_T是同一片空间但落盘数值相同没有被更新。这说明GPU的推理引擎初始化之后走前向之前一定有什么操作导致了GPU的 W_UK_T、W_UV更新而NPU没有更新的现象与GPU不一致显然存在精度问题。分析在 NPU 上进行 veRL 训练时候所有推理引擎内的 MLA 层的W_UV和W_UK_T都没更新相当于冻结了一直都是初始状态的权重。GPU 和 NPU 的 veRL 代码是同一套断点调试发现在 veRL 训练中只有在 vLLM 初始化 LLM 模型的时候才调用 1 次process_weights_after_loading()后续训练过程中推理引擎进行 update_weights 时不再调用该方法但是 GPU 的 W_UV和W_UK_T都是会自动更新的只有 NPU 并没有更新该变量。3根因1NPU contiguous 操作打断数据地址通过在process_weights_after_loading()函数中加入下面的测试代码怀疑 NPU 代码逻辑中的.contiguous()操作打断了 kv_b 矩阵的张量视图导致W_UV和W_UK_T无法自动更新。这里通过手动原地赋值的方式具体的展示了地址不一致导致内容更新不同步的现象。测试代码 1检查contiguous逻辑AssertionError: 0.0008 ! -100测试代码 2检查不带contiguous逻辑校验通过4根因2GPU 与 NPU view 行为不一致导致数据地址打断当按照前文消除掉 contiguous 的影响后在整网下发现 W_UK_T, W_UV 矩阵的权重还是没有更新说明在局部问题以外还叠加了其他问题的影响继续在 process_weights_after_loading 中进行断点调试。从头重新理清 kv_b 矩阵产生的逻辑发现在进行完这部分操作拿到初始的 kv_b_proj_weight 后观察其 data_ptr()往下执行 view 操作发现地址空间发生了改变且经过了 view 操作后原始不连续的 tensor 也变得连续了发现 GPU 上的 view 操作是不会产生新地址的 tensor 的那么问题就全部说明清楚了同时为了严谨再补上了一组不用 view 而是用 reshape 的实验发现GPU能够保证是同样一片地址空间。Dummy 权重初始时候是随机初始化权重初始根据模型结构获取到的 self.kv_b_proj 的权重在赋值给 kv_b_proj_weight 是正确的但后续经过了 view 操作再 split 生成前向计算所需要的 W_UV、W_UK_T 时拿到的权重与原始权重的数据地址已经不一致了。这部分导致在 vLLM-ascend 在 dummy 下精度出现错误并且在后续所有的训推转换流程中都会带来影响。如图所示左侧的GPU实现所有的张量从头到尾地址都是一致的右边的NPU实现在view位置和contiguous位置分别发生了两次地址变更。修复方案方案一采用在加载完权重后直接调用process_weights_after_loading确保权重始终更新适用于veRL中update_weights后的行为。方案二修复view操作使其行为与GPU一致。当前采用方案一修复已合入VeRL主仓PR #4130。精度问题 2 mindspeed的mla部分实现问题由于打通了Moonlight小模型我们有了充足的资源做其他验证。因此在定位推理问题的同时还在开展训练侧的精度对比。定位思路训练侧的定位思路就是将强化学习的训推解耦简化为预训练/微调。首先针对第一步进行校验对比前反向如果第一步没问题需要针对训推一致性继续深挖根因。本节问题定位过程中不涉及到推理的乱码问题不与【精度问题1】耦合。根因定位打桩固定rollout对比第一步前向计算loss通过打桩比对GPU和NPU前向loss计算过程时很快发现了npu和gpu存在差异差异位置是softmax_scale。定位代码差异发现mindspeed的mla模块走到FA的forward但在计算scale时由于mindspeed的mla的传参差异导致npu和gpu代码实现上存在差异。修复方案mindspeed 的实现方式是照搬了MHA、GQA实现的分母系数但是MLA上需要做单独的处理因为 q 的头的宽度是不一样的如果按照原有的流程处理scale得到的hidden_size_per_attention_head是128而DeepSeek里头q_head_dim是192修复方案https://gitcode.com/Ascend/MindSpeed/pull/2977修复后对齐NPU和GPU的前向下半部分整网验证以小见大阶段性收尾后在整网上进行验证。验证1 MLA问题修复实验目的修复2个Bug后验证精度是否有提升实验方法只修改Bug其他实验环境软件栈版本、脚本、模型等保持相同情况下对比修改Bug后的实验结果实验结果256卡cp4ep128 确定性计算 vs 256卡cp4ep64确定性计算 Mbridge MLA use_cpu实验结论修复发现的2个Bug以后671B Reward 10步可以从-0.9上升到-0.8GPU是上升到-0.6仍存在其它问题。验证2关闭临时开发的CP功能并启用Mbridge最开始和GPU对比精度的时候没有开启CP功能但由于未来有长序列训练需求有临时的MLA的CP实现同时因为本身精度存在问题推理长度不断上涨需要cp才能避免OOM既往的实验中开cp和不开cp存在混杂。由于这部分特性是训练特性没有充分验证因此在整网验证阶段关闭了精度可能存在问题的训练mla的CP功能。mbridge是权重转换的另一种方式由于GPU一致开启mbridge进行长跑因此完成适配后统一开启和GPU保持一致。蓝色曲线NPU开mbridge、带上两个修复、开CP红色曲线NPU开mbridge、带上两个修复、关CP趋势接近GPU专家认可绿色曲线GPU开mbridge、关CP整网验证通过最终通过以下手段对齐了GPU的两组配置第一组gbs32/mbs32第二组gbs128/mbs32修复MLA的scale问题修复loadformatdummy推理精度问题使能mbridge关闭未验证的MLA-CP功能第一组gbs32/mbs32开关确定性都能较好的对齐曲线第二组gbs128/mbs32红色为NPU蓝色为GPU消融mbridge为了实验的严谨性需要区分mbridge和dist权重加载方式的差异对此开展了消融实验。由于GPU只提供了使用mbridge的长跑曲线此处没有gpu加载dist权重的基线。GBS1282k-8k用例可以看到使用dist的reward曲线上升速度慢于使用mbridge。同时verl社区后续将放弃dist权重加载方式转而使用megatron版的bridge权重加载方式我们暂时没有可用的资源继续定位两者的差异。精度问题解决思路和建议总结精度第一板斧超参对齐数据集和模型结构不同则超参很可能不同因此凭借经验或论文每个论文的前提条件都不同不能一概而论给出的超参都不一定解决问题因此与GPU标杆对齐超参是排除超参问题的关键作为调整超参后训练效果的基线精度第二板斧数据集排查如果数据无法对齐则精度和模型效果无法保证对齐因此通过比对喂入模型的数据比如前10步中10步后10步 来确认数据是否对齐目的是排除硬盘数据以及从硬盘到模型之间的数据处理的差异精度第三板斧硬件压测排除精度异常硬件单机单卡任务定期1个月压测找到与其他大部分卡或机器精度不一致的机器隔离即可。精度第四板斧软件栈排查方法论1精度对齐的基本思想是相同输入相同计算 相同输出NPU和GPU是等价计算的两种软硬件实现因此在相同输入和等价计算前提下输出误差应该在合理范围内才对目前2000步 loss平均相对误差≤1%误差大的部分则通过工具或二分查找方式具体定位。方法论2理论上除了硬件以及与硬件强绑定的算子PTAPytorchAdapter外其他软件栈比如分布式训练框架等都是可以通过迁移达到NPU与GPU完全一致的因此可以在其他软件栈全部对齐下重点排查硬件和与硬件绑定的算子/PTA部分的精度误差方法论3任何精度误差排查都应该在确定性计算下进行相同权重相同数据集相同超参和环境配置开启分布式训练框架的确定性随机种子等PyTorch的确定性HCCL的确定性加载GPU的初始化权重避免随机性和配置不同导致的干扰方法论4计算算子精度误差的排查方法可以将模型减层改为单机单卡任务覆盖所有计算算子利用精度工具NPU/GPU训练对齐下从Logits代表前向计算结果和GradNorm代表前向加反向计算结果误差开始排查二分方式找出误差最大的算子当前算子精度随算子变化方法论5通信算子包括计算通信掩盖算子精度误差的排查方法通过单机梯度累积方式将单机任务与多机任务超参对齐除梯度累积外其他超参如GlobalBatchSize等都对齐对比单机与多机任务的Loss如果数据误差在1%以上则说明通信算子有问题再针对性Dump数据比对查找具体算子精度第五板斧排查模型结构权重转换等是否对齐GPU的模型结构和NPU的模型结构往往由于不同实现其是否完全等价计算需要验证排查权重转换是否完全等价也需要排查精度第六板斧排查评测打分few-shot prompt和后处理流程评分过程通常会对推理后处理部分进行修改需注意NPU和GPU打分程序保持一致。性能优化通过在VeRL上适配vllm_ascend图模式功能优化推理阶段的性能达成端到端的性能目标图模式功能适配在‎verl/workers/rollout/vllm_rollout/vllm_rollout_spmd.py 添加适配代码