
# 高可靠性前置准备：断点续训练
通过本章，您将了解到断点续训练的相关原理、配置方法、配置建议和注意事项。
由于内容较多，为便于您找到关心的内容，本节开头先做一个简单的内容分类。请参照如下分类，阅读您关心的内容。
1. 了解断点续训的概念及为什么需要断点续训，请您参考[什么是断点续训练]和[为什么需要配置断点续训练]。
2. 了解如何配置断点续训，请您参考[如何配置CheckPoint]。
3. 了解配置CheckPoint需要的注意点，请您参考[分布式训练CheckPoint注意事项]。
4. 本节为您提供了配置断点的一些建议，请您参考[CheckPoint保存频率建议]。
 #### 什么是断点续训练
断点续训练是指因为某些原因（例如容错重启、资源抢占、作业卡死等）导致训练作业还未完成就被中断，下一次训练可以在上一次的训练基础上继续进行。这种方式对于需要长时间训练的模型而言比较友好。
断点续训练是通过CheckPoint机制实现。
CheckPoint的机制是：在模型训练的过程中，不断地保存训练结果（包括但不限于EPOCH、模型权重、优化器状态、调度器状态）。即便模型训练中断，也可以基于CheckPoint继续训练。
当需要从训练中断的位置继续训练，只需要加载CheckPoint，并用CheckPoint信息初始化训练状态即可。用户需要在代码里加上reload ckpt的代码，使能读取前一次训练保存的预训练模型。具体参见[常用训练框架reload ckpt配置示例]修改对应框架ckpt配置。
 #### 为什么需要配置断点续训练
ModelArts提供的自动重启功能只能保证作业失败后重新拉起，不能保证训练进度不丢失。如果训练脚本不支持断点续训练，作业重启后可能会从头开始训练，导致如下问题：
- 已完成训练进度丢失。
- 算力资源重复消耗。
- 训练结果不符合预期。
- 多次自动重启后仍然无法恢复到故障前状态。
因此，对于耗时较长的训练任务，应优先完成CheckPoint适配。
 #### 如何配置CheckPoint
ModelArts提供了训练作业CheckPoint存储路径及自动重启机制。训练作业断点续训需要您完成如下配置才能实现。
1. [配置CheckPoint保存内容]。根据训练作业配置CheckPoint要保存的内容。
2. [配置CheckPoint保存路径]。在ModelArts上选择外置存储路径，保证CheckPoint产物能够安全持久存放，快速恢复。
3. [常用训练框架reload ckpt配置示例]。根据不同训练框架，在训练代码中配置reload CheckPoint配置。
 
 #### 配置CheckPoint保存内容
在模型训练作业执行过程中，训练作业会产生许多中间态产物，为保证断点续训能够顺利恢复作业现场，建议CheckPoint至少保存如[表1]所示内容。
本节给出相关配置项保存内容并非所有断点续训都需配置内容，请根据实际训练作业酌情参考。
 表1建议保存的CheckPoint内容 
| 内容               | 是否推荐保存 | 说明                  |
|:---|:---|:---|
| 模型权重             | 必须     | 用于恢复模型参数。           |
| 优化器状态            | 必须     | 用于恢复优化器动量、统计信息等。    |
| 当前epoch/step     | 必须     | 用于恢复训练进度。           |
| 学习率调度器状态         | 推荐     | 用于保持学习率变化一致。        |
| AMP GradScaler状态 | 推荐     | 混合精度训练场景使用。         |
| 随机数状态            | 推荐     | 用于提升恢复后训练可复现性。      |
| 数据采样器状态          | 推荐     | 分布式训练中用于恢复数据进度。     |
| 自定义训练状态          | 推荐     | 如全局step、评估指标、早停状态等。 |
   
 #### 配置CheckPoint保存路径
ModelArts提供了多种存储挂载路径方案，保证训练作业CheckPoint能安全稳定存储，即使训练作业重启后仍能够方便快速恢复训练。
断点续训练建议和训练容错检查（即自动重启）功能同时使用。在创建训练作业页面，开启"自动重启"开关。训练环境预检测失败、或者训练容器硬件检测故障、或者训练作业失败时会自动重新下发并运行训练作业。
![](https://support.huaweicloud.com/develop-modelarts/public_sys-resources/note_3.0-zh-cn.png)
建议将CheckPoint保存在稳定的共享存储或训练输出路径中，避免仅保存在容器本地目录。
为改善用户体验，ModelArts在部分站点提供了新版的控制台界面。以下分别介绍ModelArts[新版控制台]和[旧版控制台]如何设置CheckPoint存储路径。
 #### 新版控制台
在ModelArts训练中实现断点续训练或增量训练，建议使用存储挂载功能。
在创建训练作业时，通过挂载存储路径来保存和读取Checkpoint文件。具体操作如下：
1. 在训练作业中配置存储路径挂载，将存储Checkpoint的目录挂载到训练容器的本地目录。
2. 训练过程中，将Checkpoint文件保存到挂载的本地目录中，数据会自动同步到挂载的存储位置。
3. 对于断点续训练，确保挂载的存储目录中包含之前的Checkpoint文件，训练脚本会自动加载最新的Checkpoint继续训练。
通过存储挂载方式，可以实现训练数据的持久化存储和跨作业的模型复用。
在ModelArts中创建训练作业时，可以选择以下两种存储挂载选项。以下是它们的详细对比，帮助您根据需求选择合适的存储方案。
 表2两种存储挂载 
| **存储类型**      | **性能** | **容量** | **适用场景**                                      | **价格** | 备注         |
|:---|:---|:---|:---|:---|:---|
| **SFS Turbo** | 高      | 大      | 适用于多种应用场景，包括AI训练、AIGC、自动驾驶、渲染、EDA仿真、企业NAS应用等。 | 较高     | 通用         |
| **OBS**       | 中      | 大      | 基于对象存储服务作为统一数据存储的大数据场景。                       | 适中     | 高频读取，低频写入。 |
   
 #### 旧版控制台
在ModelArts训练中实现断点续训练或增量训练，建议使用"训练输出"功能。
在创建训练作业时，设置训练"输出"参数名称为"train_output"，用户可通过环境变量或超参方式获取该参数。设置成功后可在指定的训练输出的数据存储位置中保存**Checkpoint，** 且**"预下载至本地目录"** 选择"下载"。选择预下载至本地目录时，系统在训练作业启动前，自动将数据存储位置中的**Checkpoint**文件下载到训练容器的本地目录。
图1训练输出设置   
![](https://support.huaweicloud.com/develop-modelarts/figure/zh-cn_image_0000002661745357.png "点击放大")
 #### 常用训练框架reload ckpt配置示例
以下示例仅展示核心逻辑，生产环境建议增加异常处理、CheckPoint完整性校验和分布式同步。示例中设置CheckPoint保存地址变量为**train_output**。
表3常用训练框架reload ckpt配置示例 
| 训练框架          | reload ckpt配置示例                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
|:---|:---|
| VeRL          | VeRL是一个灵活、高效且被广泛使用的强化学习（RL）训练库，后训练的事实标准框架。VeRL是论文[HybridFlow: A Flexible and Efficient RLHF Framework](https://arxiv.org/abs/2409.19256v2) 的开源实现。 1. VeRL的训练yaml中配置**trainer.save_freq** 参数和**trainer.default_local_dir** 参数 VeRL通过trainer.default_local_dir参数配置输出目录，该目录下会存在多个global_steps_xx权重目录，通过trainer.save_freq参数配置权重保存的频率，每隔一定的步数保存权重。   2. VeRL的训练yaml中配置**trainer.resume_mode** 参数 当trainer.resume_mode设置为auto时，VeRL会自动遍历trainer.default_local_dir路径，加载最新且有效的ckpt。以[配置CheckPoint保存路径]中的参数名称为train_output为例，参数设置如下所示： ``` trainer.default_local_dir="${train_output}" trainer.resume_mode=auto ```                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| MindSpeed-LLM | [MindSpeed LLM](https://gitcode.com/Ascend/MindSpeed-LLM)是基于昇腾生态的大语言模型分布式训练框架，旨在为华为[昇腾芯片](https://www.hiascend.com/)生态合作伙伴提供端到端的大语言模型训练方案，包含分布式预训练、分布式指令微调以及对应的开发工具链，如：数据预处理、权重转换、在线推理、基线评估。作为昇腾计算主打的训练框架，在性能上做了极致的优化，特别在大参数、大集群和MOE类型模型的训练性能突出，且兼容Megatron-LM框架，对于Megatron客户可以平滑迁移。 1. MindSpeed-LLM中配置**--save** 参数和**--save-interval** 参数 MindSpeed-LLM训练启动脚本中通过--save参数配置输出目录，该目录下会存在多个iter_xx权重目录和一个记录最新权重保存步数的文件latest_checkpointed_iteration.txt，每次save会更新latest_checkpointed_iteration.txt。通过--save-interval参数配置权重保存的频率，每隔一定的步数保存权重。   2. MindSpeed-LLM中配置**--load** 参数，并且和--save参数路径保持一致 MindSpeed-LLM训练启动脚本中通过--load参数配置输入目录，当--save参数和--load参数设置的参数保持一致时，每次重启训练业务即可加载最新的权重，以[配置CheckPoint保存路径]中的参数名称为train_output为例，参数设置如下所示： ``` --save-interval 1000 --save ${train_output} --load ${train_output} ```                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| LLaMa-Factory | [LLaMa-Factory](https://github.com/hiyouga/LLaMA-Factory)是开源社区中一个非常活跃的大模型训练框架，它的主打特点是简单易用，通过命令行或者WebUI界面可以轻松微调数百种大模型，包括大语言和多模态模型。LLaMa-Factory的底层是基于Transformers+DeepSpeed构建，对开源模型就有非常好的兼容性。 1. LLaMa-Factory的训练yaml中配置**output_dir** 参数和**save_steps** 参数 LLaMa-Factory通过output_dir参数配置输出目录，该目录下会存在多个checkpoint-xxx权重目录，通过save_steps参数配置权重保存频率。   2. LLaMa-Factory的训练yaml中配置**resume_from_checkpoint** 参数，并且和**output_dir** 参数路径保持一致 LLaMa-Factory通过resume_from_checkpoint显式指定本次训练使用的ckpt，如果指定了有效的ckpt则从指定的ckpt中恢复训练。当resume_from_checkpoint参数和output_dir参数保持一致时，但output_dir参数不是一个有效ckpt目录，因此还需要步骤3和步骤4。以[配置CheckPoint保存路径]中的参数名称为train_output为例，参数设置如下所示： ``` ### output output_dir: ${train_output} save_steps: 500 ### train resume_from_checkpoint: ${train_output} ```   3. 首先需要创建一个resume.py脚本，该脚本需要传入训练配置yaml的绝对路径，具体代码如下所示： ``` import os import re import sys def update_resume_config(config_file):  # 接收传入的配置文件路径 # 读取配置文件内容 with open(config_file, 'r', encoding='utf-8') as f: lines = f.readlines() resume_line_num = None resume_path = None # 查找 resume_from_checkpoint 行 for i, line in enumerate(lines): if line.strip().startswith('resume_from_checkpoint:'): resume_line_num = i # 提取值 parts = line.split(':', 1) if len(parts) > 1: resume_path = parts[1].strip().strip('"\'')  # 去除引号 break # 如果没找到或值为null，不处理 if resume_line_num is None or resume_path in (None, 'null', ''): return # 检查路径并找到最新的checkpoint new_resume_path = None if os.path.isdir(resume_path): # 查找所有 checkpoint-数字 文件夹 checkpoint_pattern = re.compile(r'^checkpoint-(\d+)$') checkpoints = [] for item in os.listdir(resume_path): item_path = os.path.join(resume_path, item) if os.path.isdir(item_path): match = checkpoint_pattern.match(item) if match: step = int(match.group(1)) checkpoints.append((step, item_path)) # 如果找到checkpoint，使用最新的那个 if checkpoints: checkpoints.sort(key=lambda x: x[0]) new_resume_path = checkpoints[-1][1] # 修改配置行 indent = len(line) - len(line.lstrip())  # 保留原缩进 if new_resume_path: lines[resume_line_num] = f'{" " * indent}resume_from_checkpoint: {new_resume_path}\n' else: lines[resume_line_num] = f'{" " * indent}resume_from_checkpoint: null\n' # 写回文件 with open(config_file, 'w', encoding='utf-8') as f: f.writelines(lines) if __name__ == "__main__": # 从命令行参数中获取配置文件路径 if len(sys.argv) < 2: print("用法：python resume.py <配置文件路径>") sys.exit(1) config_file = sys.argv[1]  # 接收命令行传入的 abc.yaml update_resume_config(config_file)  # 传入函数执行 ```   4. 修改训练启动脚本，在执行llamafactory-cli train命令之前，通过resume.py脚本修改训练配置中yaml中resume_from_checkpoint参数。resume.py脚本会获取resume_from_checkpoint参数中的路径，去该路径下查找步数最大的checkpoint-xxx权重目录，然后将resume_from_checkpoint参数修改为该权重目录的绝对路径。以train_lora/deepseek3_lora_sft_kt.yaml为例，其中WORK_DIR为工作路径，shell脚本修改如下所示： ``` #!/bin/bash ... ... python $WORK_DIR/resume.py $WORK_DIR/LLaMA-Factory/examples/train_lora/deepseek3_lora_sft_kt.yaml llamafactory-cli train $WORK_DIR/LLaMA-Factory/examples/train_lora/deepseek3_lora_sft_kt.yaml ```    |
| PyTorch       | - PyTorch模型保存有两种方式。 - 仅保存模型参数 ``` state_dict = model.state_dict() torch.save(state_dict, path) ```   - 保存整个Model（不推荐） ``` torch.save(model, path) ```     - 可根据step步数、时间等周期性保存模型的训练过程的产物。 将模型训练过程中的网络权重、优化器权重、以及epoch进行保存，便于中断后继续训练恢复。 ``` checkpoint = { "net": model.state_dict(), "optimizer": optimizer.state_dict(), "epoch": epoch } if not os.path.isdir('model_save_dir'): os.makedirs('model_save_dir') torch.save(checkpoint,'model_save_dir/ckpt_{}.pth'.format(str(epoch))) ```   - 完整代码示例。 ``` import os import argparse parser = argparse.ArgumentParser() parser.add_argument("--train_output", type=str) args, unparsed = parser.parse_known_args() args = parser.parse_known_args() # train_output 将被赋值为"/home/ma-user/modelarts/outputs/train_output_0" train_output = args.train_output # 判断输出路径中是否有模型文件。如果无文件则默认从头训练，如果有模型文件，则加载epoch值最大的ckpt文件当做预训练模型。 if os.listdir(train_output): print('> load last ckpt and continue training!!') last_ckpt = sorted([file for file in os.listdir(train_output) if file.endswith(".pth")])[-1] local_ckpt_file = os.path.join(train_output, last_ckpt) print('last_ckpt:', last_ckpt) # 加载断点 checkpoint = torch.load(local_ckpt_file) # 加载模型可学习参数 model.load_state_dict(checkpoint['net']) # 加载优化器参数 optimizer.load_state_dict(checkpoint['optimizer']) # 获取保存的epoch，模型会在此epoch的基础上继续训练 start_epoch = checkpoint['epoch'] start = datetime.now() total_step = len(train_loader) for epoch in range(start_epoch + 1, args.epochs): for i, (images, labels) in enumerate(train_loader): images = images.cuda(non_blocking=True) labels = labels.cuda(non_blocking=True) # Forward pass outputs = model(images) loss = criterion(outputs, labels) # Backward and optimize optimizer.zero_grad() loss.backward() optimizer.step() ... # 保存模型训练过程中的网络权重、优化器权重、以及epoch checkpoint = { "net": model.state_dict(), "optimizer": optimizer.state_dict(), "epoch": epoch } if not os.path.isdir(train_output): os.makedirs(train_output) torch.save(checkpoint, os.path.join(train_output, 'ckpt_best_{}.pth'.format(epoch))) ```                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| MindSpore     | ``` import os import argparse from resnet import resnet50 from mindspore.nn.optim.momentum import Momentum from mindspore.nn.loss import SoftmaxCrossEntropyWithLogits from mindspore import load_checkpoint, load_param_into_net from mindspore.train import Model, CheckpointConfig, ModelCheckpoint from mindspore.train.callback import LossMonitor parser = argparse.ArgumentParser() parser.add_argument("--train_output", type=str) parser.add_argument("--batch_size", type=int, default=32, help="Batch size.") parser.add_argument("--num_classes", type=int, default=10, help="Num classes.") parser.add_argument("--do_train", type=bool, default=True, help="Do train or not.") args_opt, unparsed = parser.parse_known_args() # train_output 将被赋值为"/home/ma-user/modelarts/outputs/train_output_0"。 train_output = args_opt.train_output # 初始定义的网络、损失函数及优化器。 # 1.初始定义的网络,以“ResNet50”为例。 net = resnet50(args_opt.batch_size, args_opt.num_classes) # 2.定义损失函数。 ls = SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean") # 3.定义优化器。 opt = Momentum(filter(lambda x: x.requires_grad, net.get_parameters()), 0.01, 0.9) # 首次训练的epoch初始值，mindspore1.3及以后版本会支持定义epoch_size初始值。 # cur_epoch_num = 0 # 判断输出obs路径中是否有模型文件。如果无文件则默认从头训练，如果有模型文件，则加载epoch值最大的ckpt文件当做预训练模型。 if os.listdir(train_output): last_ckpt = sorted([file for file in os.listdir(train_output) if file.endswith(".ckpt")])[-1] print('last_ckpt:', last_ckpt) last_ckpt_file = os.path.join(train_output, last_ckpt) # 加载断点，详细请参见mindspore.load_checkpoint。 param_dict = load_checkpoint(last_ckpt_file) print('> load last ckpt and continue training!!') # 加载模型参数到net。 load_param_into_net(net, param_dict) # 加载模型参数到opt。 load_param_into_net(opt, param_dict) # 获取保存的epoch值，模型会在此epoch的基础上继续训练,此参数在mindspore1.3及以后版本会支持。 # if param_dict.get("epoch_num"): #     cur_epoch_num = int(param_dict["epoch_num"].data.asnumpy()) model = Model(net, loss_fn=ls, optimizer=opt, metrics={'acc'}) # as for train, users could use model.train if args_opt.do_train: dataset = create_dataset() batch_num = dataset.get_dataset_size() config_ck = CheckpointConfig(save_checkpoint_steps=batch_num, keep_checkpoint_max=35) # append_info=[{"epoch_num": cur_epoch_num}],mindspore1.3及以后版本会支持append_info参数，保存当前时刻的epoch值。 # 保存网络参数，详细请参见mindspore.train.ModelCheckpoint。 ckpoint_cb = ModelCheckpoint(prefix="train_resnet_cifar10", directory=args_opt.train_output, config=config_ck) loss_cb = LossMonitor() model.train(epoch_size, dataset, callbacks=[ckpoint_cb, loss_cb]) # model.train(epoch_size-cur_epoch_num, dataset, callbacks=[ckpoint_cb, loss_cb])，mindspore1.3及以后版本支持从断点恢复训练。 ```                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
   
 #### 分布式训练CheckPoint注意事项
多机多卡训练中，建议遵循以下原则：
1. 仅由rank 0保存CheckPoint，避免多个进程同时写同一个文件。
2. CheckPoint写入完成后再通过barrier同步其他进程。
3. 使用临时文件写入，再原子替换为正式文件，避免半写入文件被加载。
4. 保留最近多个CheckPoint，避免最新CheckPoint损坏后无法恢复。
5. CheckPoint件名建议包含step或epoch，并维护latest指针。
6. 恢复训练时，所有rank应加载同一个CheckPoint对应的训练进度。
7. 保存频率需要结合训练耗时、存储性能和可接受的进度损失综合设置。
 
 #### CheckPoint保存频率建议
| 训练类型     | 建议保存频率                               |
|:---|:---|
| 短时实验训练   | 每个epoch保存一次。                         |
| 普通深度学习训练 | 每N个step或每个epoch保存一次。                 |
| 大模型微调    | 每固定step保存一次，并保留多个版本。                 |
| 大模型预训练   | 根据单步耗时和故障恢复成本设置，例如每30分钟或每若干step保存一次。 |
| 强化学习训练   | 同时保存模型、优化器、环境状态和rollout相关状态。         |
   
