在昇腾 AI 生态的实践中,利用 MindSpeed-RL 工具链进行大模型强化训练是提升模型数学推理能力的关键路径。官方已发布详细的GRPO 训练教程,本文聚焦单机八卡环境下复现 DeepSeek-R1-Zero-Qwen2.5-7B 过程中的真实 Debug 经历,为开发者提供避坑指南。

一、前期准备:环境与配置验证

1. 环境搭建关键点

  • 权重转换:严格按照文档执行hf2mcore脚本,确保 Qwen-2.5-7B 权重从 HuggingFace 格式转为 Megatron-mcore 格式。注意检查脚本中target-tensor-parallel-size=2target-pipeline-parallel-size=4是否匹配单机八卡的 TP2+PP4 并行策略。
  • 数据集准备:使用 Orz math 57K 数据集,通过preprocess_data.sh r1_zero_qwen25_7b生成训练数据时,确认configs/datasets/r1_zero_qwen25_7b.yamlprompt_type正确指向 qwen_r1 模板,避免因模板缺失导致模型输出格式混乱。

2. 配置文件核对

重点检查configs/grpo_trainer_qwen25_7b.yaml中的资源分配:

yaml
actor_resource:
  num_npus: 8  # 单机八卡配置
reference_resource:
  num_npus: 8
generate_config:
  infer_tensor_parallel_size: 2  # 与权重转换时的TP配置一致
  infer_pipeline_parallel_size: 1  # 单机场景PP设为1

3.相关组件版本

驱动:24.1.0.3;
CANN:8.1.T10;
torch:2.5.1;
torch_npu:2.5.1.dev20250320

二、踩坑过程

  1. 启动训练后,第一个 iteration 报错:(train pid=2508067) RecursionError: maximum recursion depth exceeded in comparison
    整体报错如下:
[36m(train pid=2508067)[0m Unhandled error (suppress with 'RAY_IGNORE_UNHANDLED_ERRORS=1'): [36mray::compute_advantage()[39m (pid=2508417, ip=172.16.0.9)
[36m(train pid=2508067)[0m File "/data1/MindSpeed-RL/mindspeed_rl/trainer/utils/compute_utils.py", line 146, in compute_advantage
[36m(train pid=2508067)[0m while not ray.get(rb.all_consumed.remote(experience_consumer_stage)):
[36m(train pid=2508067)[0m ray.exceptions.RayTaskError(PicklingError): [36mray::GRPOTransferDock.all_consumed()[39m (pid=2515806, ip=172.16.0.9, actor_id=f9c0bd306ab82760e6f476eb01000000, repr=<mindspeed_rl.trainer.utils.transfer_dock.GRPOTransferDock object at 0xffcfeff5e800>)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/ray/cloudpickle/cloudpickle.py", line 1245, in dump
[36m(train pid=2508067)[0m return super().dump(obj)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch/storage.py", line 1219, in reduce
[36m(train pid=2508067)[0m torch.save(self, b, _use_new_zipfile_serialization=False)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch_npu/utils/serialization.py", line 255, in save
[36m(train pid=2508067)[0m return _get_npu_save_result(obj, f, pickle_module, pickle_protocol, True, _disable_byteorder_record)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch_npu/utils/serialization.py", line 236, in _get_npu_save_result
[36m(train pid=2508067)[0m result = torch.serialization.save(obj, f, pickle_module, pickle_protocol, True, _disable_byteorder_record)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch_npu/profiler/_add_mstx_patch.py", line 50, in save_wrapper
[36m(train pid=2508067)[0m out = func(*args, **kwargs)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch/serialization.py", line 850, in save
[36m(train pid=2508067)[0m _save(
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch/serialization.py", line 1088, in _save
[36m(train pid=2508067)[0m pickler.dump(obj)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch/serialization.py", line 1052, in persistent_id
[36m(train pid=2508067)[0m storage_numel = obj._size()
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch/storage.py", line 1204, in _size
[36m(train pid=2508067)[0m return self._untyped_storage.nbytes() // self._element_size()
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch_npu/utils/serialization.py", line 233, in npu_nbytes
[36m(train pid=2508067)[0m return cpu_nbytes(self)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch_npu/utils/serialization.py", line 233, in npu_nbytes
[36m(train pid=2508067)[0m return cpu_nbytes(self)
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch_npu/utils/serialization.py", line 233, in npu_nbytes
[36m(train pid=2508067)[0m return cpu_nbytes(self)
[36m(train pid=2508067)[0m [Previous line repeated 974 more times]
[36m(train pid=2508067)[0m File "/root/miniconda3/envs/ascend/lib/python3.10/site-packages/torch_npu/utils/serialization.py", line 228, in npu_nbytes
[36m(train pid=2508067)[0m if self.device.type != 'cpu':
[36m(train pid=2508067)[0m RecursionError: maximum recursion depth exceeded in comparison

问题分析:初步推测与分词器处理输入文本时的递归逻辑有关。

(1) 尝试一(失败):参考之前llama-7B使用MindSpeed-LLM训练时的相同报错,修改modelfrom_hf/lama-7b-hf/tokenizer_config.json文件。

修改前:

{"bos_token": "", "eos_token": "", "model_max_length": 1000000000000000019884624838656, "tokenizer_class": "LlamaTokenizer", "unk_token": ""}

修改后:

{"bos_token": "<s>", "eos_token": "<s>", "model_max_length": 1000000000000000019884624838656, "tokenizer_class": "LlamaTokenizer", "unk_token": "<unk>"}

修改完后并未解决。原因推测是Qwen 模型的 tokenizer 对特定模板符号(如</think>)的处理依赖内置规则,自定义符号可能破坏解析逻辑。

(2) 尝试二(成功):在/site-packages/torch_npu/utils/serialization.py注释掉下图的两行代码

需注释两行代码

原因推测:这两行代码对torch.storage.UntypedStorage.nbytes进行了修改,在torch.serialization.save操作期间,这种修改可能导致序列化过程中对象处理逻辑出现递归循环。例如,频繁切换nbytes可能使相关对象的序列化处理反复触发某些检查或操作,每次操作又进一步触发新的处理,形成递归,最终超出最大递归深度限制。注释掉这两行代码后,避免了nbytes在保存过程中的干扰性切换,使得序列化过程不再陷入这种递归循环,从而解决了RecursionError深度超限问题。

2. indexed_dataset.py, line 266, in __init__ self.length = len(list(datasets.values())[0]) IndexError: list index out of range

(1) 错误现象

在操作过程中,代码在 indexed_dataset.py, line 266, in __init__ 处报错:self.length = len(list(datasets.values())[0]) IndexError: list index out of range。这表明程序在获取数据集长度时,无法正确索引到数据集内容,暗示数据集路径或配置存在异常。

(2)原因分析

经排查,该问题很可能源于数据集格式转换时 prefix 参数与配置文件中 data_path 指向不清晰。当程序依据配置文件中的 data_path 加载数据集时,因路径与 prefix 参数配合不当,导致无法正确识别和加载数据集。这使得 datasets.values() 获取的内容为空或不符合预期,最终在取索引 [0] 时触发越界错误。

(3)解决方案

修改配置文件,将数据路径调整为 数据路径/prefix 形式。这种调整明确了数据集的具体位置与标识,确保程序能正确识别和加载数据集,避免因路径指向模糊导致 datasets 内容获取异常,进而解决 IndexError。通过此方式,datasets.values() 可正确获取数据集内容,顺利获取数据集长度,使程序恢复正常运行。

3. Bug 3:[AclOpKernelInit](https://zhida.zhihu.com/search?content_id=257549683&content_type=Article&match_order=1&q=AclOpKernelInit&zhida_source=entity) failed opTypeArangeAiCore ADD_TO_LAUNCHER_LIST_AICORE failed 问题

(1) 错误现象

训练过程中出现错误日志:
[36m(train pid=1667725)[0m AclOpKernelInit failed opType
[36m(train pid=1667725)[0m ArangeAiCore ADD_TO_LAUNCHER_LIST_AICORE failed.
这表明在操作过程中,昇腾 AI 计算核心(AiCore)相关操作初始化或执行出现异常,阻碍训练正常进行。

(2) 原因分析

经深入排查,该问题可能源于文档权重转换部分对 actor modelref model 转换权重的处理不够清晰。两者在转换权重时若未按实际需求区分配置,会导致模型权重与硬件执行配置不匹配,进而引发 AiCore 操作初始化失败。

(3) 解决方案

actor modelref model 分别进行权重转换,明确配置:

  • 针对 actor model,采用 tp8pp2(张量并行度为 8,流水线并行度为 2)进行权重转换;
  • 针对 ref model,采用 tp8pp1(张量并行度为 8,流水线并行度为 1)进行权重转换。
    通过这种区分处理,确保 actor modelref model 的权重转换与各自需求匹配,使 AiCore 操作能正确初始化与执行,从而解决上述错误,保障训练流程顺利推进。

4. Bug 4:AttributeError: module 'torch_npu' has no attribute '_npu_rotary_embedding' 问题

(1) 错误现象

运行过程中出现报错 AttributeError: module 'torch_npu' has no attribute '_npu_rotary_embedding',这表明程序在调用 torch_npu 模块中的 _npu_rotary_embedding 属性时,无法找到该属性,导致调用失败。

(2) 原因分析

经排查,此问题源于文档中 torch_npu 依赖版本 2.5.1 的描述不够清晰。实际使用中,2.5.1rc1 版本存在该属性缺失的情况,无法满足程序运行需求,从而引发错误。

(3) 解决方案

torch_npu 依赖版本从 2.5.1rc1 更改为 2.5.1.dev20250320。通过明确指定正确的开发版本,确保 torch_npu 模块包含程序所需的 _npu_rotary_embedding 属性,使程序能够正常调用该属性,避免 AttributeError,保障训练或相关操作的顺利进行。


昇腾生态正在逐步晚上,MindSpeed RL相关组件也在不断开发中,后续如有相关踩坑记录也将不断记录并分享。

上述踩坑记录感谢孙浥尘和努尔夏提同学的大力支持。希望可以帮助后续使用的开发者更容易得上手MindSpeed-RL及相应模型的强化学习!

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐