SageMaker Training Compiler 问题排查 - Amazon SageMaker
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

SageMaker Training Compiler 问题排查

在遇到错误时,您可以根据以下列表尝试对训练作业进行问题排查。如果您需要进一步的支持,请通过 Amazon 支持Amazon SageMaker 的 Amazon 开发人员论坛联系 SageMaker 团队。

与本机框架训练作业相比,训练作业未按预期收敛

收敛问题涵盖了从“模型在 SageMaker Training Compiler 启动时无法学习”到“模型正在学习,但比本机框架慢”的各种问题。在本问题排查指南中,我们假定在没有 SageMaker Training Compiler(本机框架中)的情况下您的收敛效果很好,并将其视为基准。

在遇到此类收敛问题时,第一步是确定问题是限于分布式训练还是源于单 GPU 训练。使用 SageMaker Training Compiler 进行分布式训练是对单 GPU 训练的扩展,增加了额外步骤。

  1. 设置具有多个实例或 GPU 的集群。

  2. 将输入数据分发给所有工作线程。

  3. 同步来自所有工作线程的模型更新。

因此,单 GPU 训练中的任何收敛问题都会传播到具有多个工作线程的分布式训练。

A flow chart to troubleshoot convergence issues in training jobs when using SageMaker Training Compiler. Descriptions are in the following sections.

单 GPU 训练中出现的收敛问题

如果您的收敛问题源于单 GPU 训练,则可能是由于超参数或 torch_xla API 的设置不当所致。

检查超参数

使用 SageMaker Training Compiler 进行训练会导致模型的内存占用量发生变化。编译器会智能地在重用和重新计算之间进行仲裁,从而相应地增加或减少内存使用量。要利用这一点,必须在将训练作业迁移到 SageMaker Training Compiler 时,重新调整批处理大小和相关的超参数。但是,错误的超参数设置通常会导致训练损失振荡,并可能最终导致较慢的收敛速度。在极少数情况下,激进的超参数可能会导致模型无法学习(训练损失指标不会减少或返回 NaN)。要确定收敛问题是否由超参数引起,请在保持所有超参数不变的情况下,对两个分别使用和不使用 SageMaker Training Compiler 的训练作业进行并排测试。

检查是否已针对单 GPU 训练正确设置 torch_xla API

如果基准超参数仍存在收敛问题,则需要检查是否存在不当使用 torch_xla API 的情况,特别是用于更新模型的 API。基本上,torch_xla 继续以图表形式累积指令(延迟执行),直到明确指示它运行累积的图表。torch_xla.core.xla_model.mark_step() 函数可推进累积图的执行。每次模型更新后以及打印和记录任何变量前,都应使用此函数同步图表的执行。如果它缺少同步步骤,模型可能会在打印、记录和后续正向传递过程中使用内存中的旧值,而不是使用每次迭代和模型更新后都必须同步的最新值。

将 SageMaker Training Compiler 与梯度扩展(可能来自使用 AMP)或梯度剪辑技术结合使用时,情况可能会更加复杂。使用 AMP 进行梯度计算的相应顺序如下。

  1. 使用扩展进行梯度计算

  2. 梯度取消扩展、梯度裁剪,然后扩展

  3. 模型更新

  4. 使用 mark_step() 同步图表执行

要找到适合列表中提到的操作的 API,请参阅有关将训练脚本迁移到 SageMaker Training Compiler 的指南。

考虑使用自动模型调整

如果在使用 SageMaker Training Compiler 时重新调整批处理大小和相关的超参数(例如学习率)时出现收敛问题,请考虑使用自动模型调整来调整超参数。您可以参考有关使用 SageMaker Training Compiler 调整超参数的示例笔记本

分布式训练中出现的收敛问题

如果分布式训练中仍存在收敛问题,则可能是由于权重初始化或 torch_xla API 的设置不当所致。

检查跨工作线程的权重初始化

如果在运行包含多个工作线程的分布式训练作业时出现收敛问题,请通过在适用时设置恒定种子来确保所有工作线程的确定性行为一致。请注意权重初始化等涉及随机掩码的技术。在没有恒定种子的情况下,每个工作线程最终可能会训练不同的模型。

检查是否已针对分布式训练正确设置 torch_xla API

如果问题仍然存在,则可能是因不当使用 torch_xla API 进行分布式训练所致。请务必在估算器中添加以下内容,以便使用 SageMaker Training Compiler 为分布式训练设置集群。

distribution={'torchxla': {'enabled': True}}

这应在训练脚本中附带函数 _mp_fn(index),为每个工作线程调用该函数一次。如果没有 mp_fn(index) 函数,您最终可能会让每个工作线程单独训练模型,而不共享模型更新。

接下来,请确保按照有关将训练脚本迁移到 SageMaker Training Compiler 的文档中的指导,将 torch_xla.distributed.parallel_loader.MpDeviceLoader API 与分布式数据取样器一起使用,如以下示例所示。

torch.utils.data.distributed.DistributedSampler()

这可确保输入数据在所有工作线程之间正确分配。

最后,要同步所有工作线程的模型更新,请使用 torch_xla.core.xla_model._fetch_gradients 收集所有工作线程的梯度,并使用 torch_xla.core.xla_model.all_reduce 将所有收集到的梯度合并为一个更新。

将 SageMaker Training Compiler 与梯度扩展(可能来自使用 AMP)或梯度裁剪技术结合使用时,情况可能会更加复杂。使用 AMP 进行梯度计算的相应顺序如下。

  1. 使用扩展进行梯度计算

  2. 跨所有工作线程的梯度同步

  3. 梯度取消扩展、梯度裁剪,然后梯度扩展

  4. 模型更新

  5. 使用 mark_step() 同步图表执行

请注意,与单 GPU 训练的清单相比,此清单还有一个用于同步所有工作线程的额外项目。

由于缺少 PyTorcl/XLA 配置,训练作业失败

如果训练作业失败,且出现 Missing XLA configuration 错误消息,则可能是因错误配置了所使用的每实例 GPU 数导致的。

XLA 需要额外的环境变量来编译训练作业。缺少的最常见环境变量是 GPU_NUM_DEVICES。要使编译器正常工作,您必须将此环境变量的值设置为每实例 GPU 数。

可以通过三种方法设置 GPU_NUM_DEVICES 环境变量:

  • 方法 1 – 使用 SageMaker 估算器类的 environment 参数。例如,如果您使用具有四个 GPU 的 ml.p3.8xlarge 实例,请执行以下操作:

    # Using the SageMaker Python SDK's HuggingFace estimator hf_estimator=HuggingFace( ... instance_type="ml.p3.8xlarge", hyperparameters={...}, environment={ ... "GPU_NUM_DEVICES": "4" # corresponds to number of GPUs on the specified instance }, )
  • 方法 2 – 使用 SageMaker 估算器类的 hyperparameters 参数并在训练脚本中解析它。

    1. 要指定 GPU 的数量,请将键值对添加到 hyperparameters 参数。

      例如,如果您使用具有四个 GPU 的 ml.p3.8xlarge 实例,请执行以下操作:

      # Using the SageMaker Python SDK's HuggingFace estimator hf_estimator=HuggingFace( ... entry_point = "train.py" instance_type= "ml.p3.8xlarge", hyperparameters = { ... "n_gpus": 4 # corresponds to number of GPUs on specified instance } ) hf_estimator.fit()
    2. 在您的训练脚本中,解析 n_gpus 超参数并将其指定为 GPU_NUM_DEVICES 环境变量的输入。

      # train.py import os, argparse if __name__ == "__main__": parser = argparse.ArgumentParser() ... # Data, model, and output directories parser.add_argument("--output_data_dir", type=str, default=os.environ["SM_OUTPUT_DATA_DIR"]) parser.add_argument("--model_dir", type=str, default=os.environ["SM_MODEL_DIR"]) parser.add_argument("--training_dir", type=str, default=os.environ["SM_CHANNEL_TRAIN"]) parser.add_argument("--test_dir", type=str, default=os.environ["SM_CHANNEL_TEST"]) parser.add_argument("--n_gpus", type=str, default=os.environ["SM_NUM_GPUS"]) args, _ = parser.parse_known_args() os.environ["GPU_NUM_DEVICES"] = args.n_gpus
  • 方法 3 – 对训练脚本中的 GPU_NUM_DEVICES 环境变量进行硬编码。例如,如果您使用的实例具有四个 GPU,请将以下内容添加到脚本中。

    # train.py import os os.environ["GPU_NUM_DEVICES"] = 4
提示

要查找机器学习实例上要使用的 GPU 设备数量,请参阅 Amazon EC2 实例类型页面中的加速计算

SageMaker Training Compiler 不会减少总训练时间

如果使用 SageMaker Training Compiler 未减少总训练时间,我们强烈建议您仔细查看 SageMaker Training Compiler 最佳实践和注意事项 页面,检查您的训练配置、输入张量形状的填充策略以及超参数。