README.md

分析迁移工具

简介

昇腾NPU是AI算力的后起之秀,但目前训练和在线推理脚本大多是基于GPU的。由于NPU与GPU的架构差异,基于GPU的训练和在线推理脚本不能直接在NPU上使用。

分析迁移工具(msTransplant,MindStudio Transplant)提供PyTorch训练脚本一键式迁移至昇腾NPU的功能,开发者可做到少量代码修改或零代码完成迁移。该工具提供PyTorch Analyse功能,帮助用户分析PyTorch训练脚本的API、第三方库API、亲和API分析以及动态shape的支持情况。同时提供了自动迁移和PyTorch GPU2Ascend工具两种迁移方式,将基于GPU的脚本迁移为基于NPU的脚本,这种自动化方法节省了人工手动进行脚本迁移的学习成本与工作量,大幅提升了迁移效率。

  • (推荐)自动迁移:修改内容少,只需在训练脚本中导入库代码,迁移后直接在昇腾NPU平台上运行。
  • PyTorch GPU2Ascend工具迁移:迁移过程会生成分析文件,支持用户查看API支持度分析报告和迁移过程中对原训练脚本的修改内容,并支持单卡脚本迁移为多卡脚本。

说明

使用分析迁移工具迁移前,请用户自行确认原工程内各参数的正确性,需在原工程运行成功的基础上使用工具进行迁移。

使用前准备

环境准备

该工具功能的实际执行仅依赖CPU,且需提前安装以下必选依赖:

pip3 install pandas         # 必选,pandas版本号需大于或等于1.2.4
pip3 install libcst         # 必选,语义分析库,用于解析Python文件
pip3 install prettytable    # 必选,将数据可视化为图表形式
pip3 install jedi           # 必选,用于跨文件解析

迁移功能执行完成后,若需在NPU上运行迁移后的训练脚本,还需完成以下额外依赖的安装:

  • 安装配套版本的CANN Toolkit开发套件包和ops算子包,请参见《CANN 软件安装指南》。

  • 配置环境变量。

    安装CANN软件后,使用CANN运行用户进行编译、运行时,需要以CANN运行用户登录环境,执行source $_{install_path}_set_env.sh命令设置环境变量。其中${install_path}为CANN软件的安装目录,例如:/usr/local/Ascend/cann。

    说明

    上述环境变量只在当前窗口生效,用户可以将上述命令写入~.bashrc文件,使其永久生效,操作如下:

    1. 以安装用户在任意目录下执行vi ~.bashrc,打开.bashrc文件,并在该文件最后添加上述环境变量。
    2. 执行:wq!命令,保存文件并退出。
    3. 执行source ~.bashrc命令,使环境变量生效。

约束

  • 分析和迁移工具当前支持PyTorch2.1.0、2.6.0、2.7.1、2.8.0版本训练脚本的分析和迁移。
  • 原脚本需要在GPU环境下且基于Python3.7及以上能够运行成功。
  • 分析迁移后的执行逻辑与迁移前需保持一致。
  • 若原始代码中调用了第三方库,迁移过程可能会存在适配问题。在迁移原始代码前,用户需要根据已调用的第三方库,自行安装昇腾已适配的第三方库版本,已适配的第三方库信息和使用指南请参考《Ascend Extension for PyTorch 套件与三方库支持清单》。
  • APEX中使用的FusedAdam优化器不支持使用自动迁移和PyTorch GPU2Ascend工具进行迁移,若原始代码中包含该优化器,用户需自行修改。
  • 当前分析工具不支持对原生函数self.dropout()、nn.functional.softmax()、torch.add、bboexs_diou()、bboexs_giou()、LabelSmoothingCrossEntropy()或ColorJitter进行亲和API分析,若原训练脚本涉及以上原生函数,请参考《Ascend Extension for PyTorch 自定义API参考》中“Python接口 > torch_npu.contrib”节点进行分析和替换。
  • 若用户训练脚本中包含昇腾NPU平台不支持的amp_C模块,需要用户手动删除import amp_C相关代码内容后,再进行训练。
  • 由于转换后的脚本与原始脚本平台不一致,迁移后的脚本在调试运行过程中可能会由于算子差异等原因而抛出异常,导致进程终止,该类异常需要用户根据异常信息进一步调试解决。

安全注意事项

  • 在Linux环境使用工具时,出于安全性及权限最小化角度考虑,本工具不应使用root等高权限账户进行操作,建议使用普通用户权限安装执行。
  • 在Linux环境使用工具时,请确保使用前执行用户的umask值大于等于0027,否则可能会造成工具生成的数据文件和目录权限过大。
  • 在Linux环境使用工具时,用户须自行保证使用最小权限原则,如给工具输入的文件要求other用户不可写,在一些对安全要求更严格的功能场景下还需确保输入的文件group用户不可写。
  • 由于本工具依赖CANN,为保证安全,应使用同一低权限用户默认安装的CANN包,source命令执行后请不要随意修改set_env.sh中涉及的环境变量。
  • 本工具为开发调测工具,不建议在生产环境使用。

快速入门

概述

分析迁移工具可将基于GPU的训练脚本迁移为支持NPU的脚本,大幅度提高脚本迁移速度,降低开发者的工作量。本样例可以让开发者快速体验自动迁移(推荐)和PyTorch GPU2Ascend工具的迁移效率。

本样例选用ResNet50模型,数据集为ImageNet。

环境准备

自动迁移(推荐)

修改内容少,只需在训练脚本中导入库代码,迁移后直接在昇腾NPU平台上运行。

  1. 在训练脚本main.py文件中导入自动迁移的库代码。

    from torch.utils.data import Subset
    import torch_npu 
    from torch_npu.contrib import transfer_to_npu   
    .....
    
  2. 切换目录至迁移完成后的训练脚本所在路径(以/home/user为例),执行以下命令使用虚拟数据集进行训练,迁移完成后的训练脚本可在NPU上正常运行。

    开始打印迭代日志,说明训练功能迁移成功。

    cd /home/user
    python main.py -a resnet50 --gpu 1 --epochs 1 --dummy  # --gpu 1表示使用卡1,--epochs 1是指迭代次数为1
    
  3. 迁移工具自动保存权重成功,说明迁移成功。

使用PyTorch GPU2Ascend工具迁移

  1. 进入迁移工具所在路径。

    cd msfmktransplt/src/ms_fmk_transplt/  
    
  2. 执行脚本迁移任务,参考表 6 参数说明配置信息。

    bash pytorch_gpu2npu.sh -i /home/user -o /home/out -v 2.1.0  
    

    /home/user为原始脚本路径, /home/out为脚本迁移结果输出路径,2.1.0为原始脚本的PyTorch框架版本。

  3. 切换目录至迁移完成后的训练脚本所在路径(以/home/user为例),执行以下命令使用虚拟数据集进行训练,迁移完成后的训练脚本可在NPU上正常运行。

    开始打印迭代日志,说明训练功能迁移成功。

    cd /home/user
    python main.py -a resnet50 --gpu 1 --epochs 1 --dummy  # --gpu 1表示使用卡1,--epochs 1是指迭代次数为1
    
  4. 完成脚本迁移,进入脚本迁移结果的输出路径查看结果件。

    说明

    脚本迁移过程中会启动迁移分析,默认使用torch_apis和affinity_apis的分析模式,可参见输出结果文件说明查看对应的结果件。

  5. 迁移工具自动保存权重成功,说明迁移成功。

迁移分析

功能说明

PyTorch Analyse工具提供分析脚本,帮助用户在执行迁移操作前,分析基于GPU平台的PyTorch训练脚本中API、第三方库套件、亲和API分析以及动态shape的支持情况,具体请参见表 1 分析模式介绍

分析脚本所在路径为:msfmktransplt/src/ms_fmk_transplt/pytorch_analyse.sh。

表 1 分析模式介绍

分析模式 分析脚本 分析结果 调优建议
第三方库套件分析模式 需用户提供待分析的第三方库套件源码。 可快速获得源码中不支持的第三方库API和CUDA信息。
说明:第三方库API是指在第三方库代码中的函数,如果某函数的函数体内使用了不支持的torch算子或者CUDA自定义算子,则此函数就是第三方库不支持的API。如果第三方库中其他函数调用了这些不支持的API,则这些调用函数也为不支持的API。
-
API支持情况分析模式 需用户提供待分析的PyTorch训练脚本。 可快速获得训练脚本中不支持的torch API和CUDA API信息。 输出训练脚本中API精度和性能调优的专家建议。
动态shape分析模式 需用户提供待分析的PyTorch训练脚本。 可快速获得训练脚本中包含的动态shape信息。 -
亲和API分析模式 需用户提供待分析的PyTorch训练脚本。 可快速获得训练脚本中可替换的亲和API信息。 -

命令格式

bash pytorch_analyse.sh -i <input> -o <output> -v <version> [-m <mode>] [-env <env_path>] [-api <api_files>]

其中“[]”表示可选参数,实际使用可不用添加;“<>”表示变量。

参数说明

表 2 参数说明

参数 可选/必选 参数说明
-i或--input 必选 待分析脚本文件所在文件夹或第三方库套件源码所在文件夹路径。
-o或--output 必选 分析结果文件的输出路径。会在该路径下生成xxxx_analysis文件夹。用户需确保分析结果文件的输出路径在运行前存在,否则分析迁移工具会提示error。
-v或--version 必选 待分析脚本或第三方库套件源码的PyTorch版本。
-m或--mode 可选 分析的模式。默认值为torch_apis。取值为:
• torch_apis:API支持情况分析
• third_party:第三方库套件分析
• affinity_apis:亲和API分析
• dynamic_shape:动态shape分析
-env或--env-path 可选 分析时需要增加的PYTHONPATH环境变量路径,仅安装jedi后该参数才生效。
指定的第三方库待分析的路径,分析当前脚本中不支持的第三方库的API列表。
-api或--api-files 可选 第三方库不支持API的分析结果文件。
若第三方库存在不支持的API,且自定义函数调用了不支持的torch API,可使用分析torch API的功能。
-h或--help 可选 打印帮助信息。

使用示例(API支持情况分析)

  1. 进入分析工具所在路径。

    cd msfmktransplt/src/ms_fmk_transplt
    
  2. 启动分析任务。

    参考表2 参数说明配置信息,执行如下命令启动分析任务。

    bash pytorch_analyse.sh -i /home/xxx/analysis -o /home/xxx/analysis_output -v 2.1.0    
    

    其中/home/xxx/analysis为待分析脚本路径,/home/xxx/analysis_output为分析结果输出路径,2.1.0为待分析脚本框架版本。

    -m参数指定的分析模式为dynamic_shape,分析任务完成后需参考训练配置对训练脚本进行修改,才能获取动态shape分析报告。

  3. 分析完成后,进入脚本分析结果输出路径,查看分析报告,具体请参见输出结果文件说明

使用示例(不支持迁移的第三方库API信息分析)

  1. 进入分析工具所在路径。

    cd msfmktransplt/src/ms_fmk_transplt
    
  2. 使用-m参数的third_party第三方库套件分析功能,获得第三方库中不支持迁移的API列表(csv文件)。

    bash pytorch_analyse.sh -i third_party_input_path -o third_party_output_path -v 2.1.0 -m third_party  
    

    third_party_input_path为第三方库文件夹路径,third_party_output_path为结果输出路径,2.1.0为待分析脚本框架版本。

    该命令执行完成后,在third_party_output_path目录下生成第三方库中不支持迁移的API列表,即framework_unsupported_op.csv文件。

  3. 将上述步骤中获取的csv文件传入-api,获取当前训练脚本中不支持迁移的三方库API信息。

    bash pytorch_analyse.sh -i input_path -o output_path -v 2.1.0 -api third_party_output_path/framework_unsupported_op.csv
    

    input_path为模型脚本文件夹路径,output_path为结果输出路径。

  4. 分析完成后,进入脚本分析结果输出路径,查看分析报告,具体请参见输出结果文件说明

输出结果文件说明

  • 分析模式为“torch_apis“时,分析结果如下所示:

    ├── xxxx_analysis     // 分析结果输出目录
    │   ├── cuda_op_list.csv             // CUDA API列表
    │   ├── unknown_api.csv              // 支持存疑的API列表
    │   ├── unsupported_api.csv          // 不支持的API列表
    │   ├── api_precision_advice.csv    // API精度调优的专家建议
    │   ├── api_performance_advice.csv  // API性能调优的专家建议
    │   ├── pytorch_analysis.txt         // 分析过程日志
    

    表 3 “torch_apis“模式csv文件介绍

    文件名 简介
    unsupported_api.csv 当前框架不支持的API列表,可以在昇腾开源社区寻求帮助。具体可参见图1 不支持的API列表示例
    cuda_op_list.csv 当前训练脚本包含的CUDA API信息。
    unknown_api.csv 支持存疑的API列表,具体的PyTorch API信息请参见表4 PyTorch API接口信息。如果训练失败,可以到昇腾开源社区求助。
    api_precision_advice.csv 当前训练脚本中可以进行精度调优的专家建议,除此之外,还可以使用msProbe工具进行调优。
    api_performance_advice.csv 当前训练脚本中可以进行性能调优的专家建议和指导措施,除此之外,还可以使用Ascend PyTorch Profiler工具进行调优。分析结果基于原生PyTorch框架的API接口信息,具体请参见表4 PyTorch API接口信息

    图1 不支持的API列表示例

    表 4 PyTorch API接口信息

    PyTorch框架版本

    API信息参考链接

    Ascend Extension for PyTorch版本

    CANN版本

    2.8.0

    PyTorch2.8.0

    7.2.0

    商用版:8.3.RC1

    社区版:8.3.RC1

    2.7.1

    PyTorch2.7.1

    2.6.0

    PyTorch2.6.0

    7.1.0

    商用版:8.2.RC1

    社区版:8.2.RC1

    2.5.1

    PyTorch2.5.1

    2.3.1

    PyTorch2.3.1

    2.5.1

    PyTorch2.5.1

    7.0.0

    商用版:8.1.RC1

    社区版:8.1.RC1

    2.4.0

    PyTorch2.4.0

    2.3.1

    PyTorch2.3.1

    2.1.0

    PyTorch2.1.0

    2.1.0

    PyTorch 2.1.0

    6.0.0

    商用版:8.0.0

    社区版:8.0.0.beta1

    2.3.1

    PyTorch 2.3.1

    2.4.0

    PyTorch 2.4.0

    2.1.0

    PyTorch 2.1.0

    6.0.rc3

    商用版:8.0.RC3

    社区版:8.0.RC3.beta1

    2.3.1

    PyTorch 2.3.1

    2.4.0

    PyTorch 2.4.0

    1.11.0

    PyTorch 1.11.0

    6.0.rc2

    商用版:8.0.RC2

    社区版:8.0.RC2.beta1

    2.1.0

    PyTorch 2.1.0

    2.2.0

    PyTorch 2.2.0

    2.3.1

    PyTorch 2.3.1

    1.11.0

    PyTorch 1.11.0

    6.0.rc1

    商用版:8.0.RC1

    社区版:8.0.RC1.beta1

    2.1.0

    PyTorch 2.1.0

    2.2.0

    PyTorch 2.2.0

  • 分析模式为“third_party“时,分析结果如下所示:

    ├── xxxx_analysis     // 分析结果输出目录
    │   ├── cuda_op.csv                  // CUDA API列表
    │   ├── framework_unsupported_op.csv // 框架不支持的API列表
    │   ├── full_unsupported_results.csv // 全量不支持的API列表
    │   ├── migration_needed_op.csv      // 待迁移的API列表
    │   ├── unknown_op.csv              // 支持情况存疑的API列表
    │   ├── pytorch_analysis.txt         // 分析过程日志
    

    表 5 “third_party”模式csv文件介绍

    文件名 简介
    framework_unsupported_op.csv 框架不支持的API列表,查看第三方库源码中当前框架不支持的第三方库API。对于当前框架不支持的API,可以到昇腾开源社区寻求帮助。具体可参见图2 不支持的API列表示例
    cuda_op.csv 当前第三方库源码包含的CUDA API信息。
    full_unsupported_results.csv 全量不支持的API列表,由于不支持CUDA和PyTorch框架而导致不支持第三方库的API列表。可以在其他调用已分析第三方库源码的训练脚本执行分析操作时,使用-api指定,帮助用户快速获得分析结果。
    migration_needed_op.csv 待迁移的API列表,列表中的API支持使用迁移工具进行迁移。
    unknown_op.csv 支持情况存疑的API列表。如果训练失败,可以到昇腾开源社区求助。

    图2 不支持的API列表示例

  • 分析模式为“affinity_apis“时,分析结果如下所示:

    ├── xxxx_analysis // 分析结果输出目录
    │   ├──  affinity_api_call.csv      // 可替换为亲和API的原生API调用列表
    │   ├──  pytorch_analysis.txt       // 分析过程日志
    

    分析报告affinity_api_call.csv包括原生API的调用信息,并将其分为几种类型:class(类)、function(方法)、torch(Pytorch框架API)以及special(特殊表达式)。用户可以根据分析报告,在训练脚本中将原生API手动替换为指定的亲和API,替换后的脚本在昇腾AI处理器上运行时,性能更优。分析报告示例如下。

    图3 亲和API分析报告示例

  • 分析模式为“dynamic_shape”时,分析结果如下所示:

    ├── xxxx_analysis                   // 分析结果输出目录
    │   ├── 生成脚本文件                 // 与分析前的脚本文件目录结构一致
    │   ├── msft_dynamic_analysis
    │         ├── hook.py              // 包含动态shape分析的功能参数
    │         ├── __init__.py
    

    生成动态shape分析结果件后,还需要先修改分析结果输出目录下训练脚本文件中的读取训练数据集的for循环,手动开启动态shape检测,请参考下方示例进行修改。

    修改前:

    for i, (ings, targets, paths, _) in pbar:
    

    修改后:

    for i, (ings, targets, paths, _) in DETECTOR.start(pbar) :
    

    运行分析修改后的训练脚本,将在分析结果件所在的根目录下生成保存动态shape的分析报告msft_dynamic_shape_analysis_report.csv。

    说明

    • 动态shape分析得到的模型训练脚本文件建议在GPU上执行。若已完成模型训练脚本文件迁移且需要在NPU上运行时,则存在动态shape的算子运行时间将会较长。
    • 若生成的msft_dynamic_shape_analysis_report.csv文件内容为空时,表示训练脚本中没使用动态shape。

迁移训练

自动迁移方式

功能说明

本章节将指导用户将PyTorch训练脚本从GPU平台迁移至昇腾NPU平台。自动迁移方式支持PyTorch2.1.0、2.6.0、2.7.1、2.8.0版本的训练脚本的迁移,自动迁移方式较简单,且修改内容最少,只需在训练脚本中导入库代码。

注意事项

  • 由于自动迁移工具使用了Python的动态特性,但torch.jit.script不支持Python的动态语法,因此用户原训练脚本中包含torch.jit.script时使用自动迁移功能会产生冲突。目前自动迁移时会屏蔽torch.jit.script功能,若用户脚本中必须使用torch.jit.script功能,请使用PyTorch GPU2Ascend工具迁移方式进行迁移。
  • 自动迁移工具与昇腾已适配的第三方库可能存在功能冲突,若发生冲突,请使用PyTorch GPU2Ascend工具迁移方式进行迁移。
  • 当前自动迁移暂不支持channel_last特性,建议用户使用contiguous进行替换。
  • 若原脚本中使用的backend为nccl,在init_process_group初始化进程组后,backend已被自动迁移工具替换为hccl。如果后续代码逻辑包含backend是否为nccl的判断,例如assert backend in ['gloo', 'nccl']、if backend == 'nccl',请手动将字符串nccl改写为hccl。
  • 若用户训练脚本中包含昇腾NPU平台不支持的torch.cuda.default_generators接口,需要手动修改为torch_npu.npu.default_generators接口。

迁移操作使用示例

  1. 导入自动迁移的库代码。

    在训练入口.py文件的首行,插入以下引用内容。例如train.py中的首行插入以下引用内容。

    import torch
    import torch_npu
    from torch_npu.contrib import transfer_to_npu   
    .....
    
  2. 迁移操作完成。请参考训练配置及原始脚本提供的训练流程,在昇腾NPU平台直接运行修改后的模型脚本。

  3. 训练完成后,迁移工具自动保存权重成功,说明迁移成功。若迁移失败,请参考迁移异常处理进行解决。

迁移异常处理

  • 如果模型包含评估、在线推理功能,也可在对应脚本中导入自动迁移库代码,并通过对比评估推理结果和日志打印情况,判断与GPU、CPU是否一致决定是否迁移成功。
  • 若训练过程中提示部分CUDA接口报错,可能是部分API(算子API或框架API)不支持引起,用户可参考以下方案进行解决。

PyTorch GPU2Ascend工具迁移方式

功能说明

本章节介绍PyTorch GPU2Ascend工具的迁移方式。

注意事项

  • 由于转换后的脚本与原始脚本平台不一致,迁移后的脚本在调试运行过程中可能会由于算子差异等原因而出现异常,导致进程终止,该类异常需要用户根据异常信息进一步调试解决。
  • 分析迁移后可以参考原始脚本提供的训练流程进行训练。

命令格式

#单卡
bash pytorch_gpu2npu.sh -i <input> -o <output> -v <version> [-s]
#分布式
bash pytorch_gpu2npu.sh -i <input> -o <output> -v <version>  [-s] distributed -m [-t <model>]

其中“[]”表示可选参数,实际使用可不用添加;“<>”表示变量。

参数说明

表 6 参数说明

参数 是否必选 参数说明
-i或--input 必选。 要进行迁移的原始脚本文件所在文件夹路径。
-o或--output 必选。 脚本迁移结果文件输出路径。不开启distributed即迁移至单卡脚本场景下,输出目录名为xxx_msft;开启distributed即迁移至多卡脚本场景下,输出目录名为xxx_msft_multi,xxx为原始脚本所在文件夹名称。
-v或--version 必选。 待迁移脚本的PyTorch版本。
-s或--specify-device 可选。 可以通过环境变量DEVICE_ID指定device作为高级特性,但有可能导致原本脚本中分布式功能失效。
distributed -m/--main:必选。
-t/--target_model:可选。
将GPU单卡脚本迁移为NPU多卡脚本,仅支持使用torch.utils.data.DataLoader方式加载数据的场景说明。指定此参数后,才可以指定-t/--target_model参数。
-m/--main:训练脚本的入口Python文件。
-t/--target_model:待迁移脚本中的实例化模型变量名,默认为“model”,如果变量名不为"model"时,则需要配置此参数,例如"my_model = Model()",需要配置为-t my_model。
-h或--help - 打印帮助信息。

使用示例

  1. 进入迁移工具所在路径。

    cd msfmktransplt/src/ms_fmk_transplt  
    
  2. 启动迁移任务。

    参考表 6 参数说明配置信息,执行如下命令启动迁移任务。

    bash pytorch_gpu2npu.sh -i /home/username/fmktransplt -o /home/username/fmktransplt_output -v 2.1.0 distributed -m /home/train/train.py   
    

    其中/home/username/fmktransplt为原始脚本路径,/home/username/fmktransplt_output为脚本迁移结果输出路径,2.1.0为原始脚本框架版本,/home/train/train.py为训练脚本的入口文件,model为目标模型变量名。distributed及其参数-m、-t在语句最后指定。

    参考示例:

    # 单卡
    bash pytorch_gpu2npu.sh -i /home/train/ -o /home/out -v 2.1.0 
    # 分布式
    bash pytorch_gpu2npu.sh -i /home/train/ -o /home/out -v 2.1.0  distributed -m /home/train/train.py 
    
  3. 完成脚本迁移,进入脚本迁移结果的输出路径查看结果件。

    说明

  4. 请参考训练配置及原始脚本提供的训练流程,在昇腾NPU平台直接运行修改后的模型脚本。

  5. 成功保存权重,说明保存权重功能迁移成功。

  6. 训练完成后,迁移工具自动保存权重成功,说明迁移成功。

训练配置

功能说明

本章节主要介绍在特殊场景中进行模型迁移训练时需要注意的配置事项。

注意事项

无。

使用示例

  • 为了提升模型运行速度,建议开启使用二进制算子,请参考《CANN 软件安装指南》中的“安装CANN”章节安装Toolkit开发套件包及ops算子包后,参考如下方式开启:

    • 单卡场景下,修改训练入口文件例如main.py文件,在import torch_npu下方添加如下代码。

      import torch
      import torch_npu
      torch_npu.npu.set_compile_mode(jit_compile=False)
      ......
      
    • 多卡场景下,如果拉起多卡训练的方式为mp.spawn,则torch_npu.npu.set_compile_mode(jit_compile=False)必须加在进程拉起的主函数中才能使能二进制,否则使能方式与单卡场景相同。

      if is_distributed:
          mp.spawn(main_worker, nprocs=ngpus_per_node, args=(ngpus_per_node, args))
      else:
          main_worker(args.gpu, ngpus_per_node, args)
      def main_worker(gpu, ngpus_per_node, args):
          # 加在进程拉起的主函数中
         torch_npu.npu.set_compile_mode(jit_compile=False)
          ......
      
  • 用户训练脚本中包含昇腾NPU平台不支持的torch.nn.DataParallel接口,需要手动修改为torch.nn.parallel.DistributedDataParallel接口执行多卡训练,参考GPU单卡脚本迁移为NPU多卡脚本进行修改。

  • 若用户训练脚本中包含昇腾NPU平台不支持的amp_C模块,需要用户手动删除import amp_C相关代码内容后,再进行训练。

  • 若用户训练脚本中包含torch.cuda.get_device_capability接口,迁移后在昇腾NPU平台上运行时,会返回“None”值。

    说明

    GPU平台调用torch.cuda.get_device_capability接口时,会返回数据类型为Tuple[int, int]的GPU算力值。而NPU平台的torch.npu.get_device_capability接口没有相应概念,会返回“None”。若遇报错,需要用户将“None”值手动修改为Tuple[int, int]类型的固定值。

  • torch.cuda.get_device_properties接口迁移后在昇腾NPU平台上运行时,返回值不包含minor和major属性,建议用户注释掉调用minor和major属性的代码。

案例

使用torch.utils.data.DataLoader方式加载数据的场景说明

torch.utils.data.DataLoader是PyTorch中一个用于数据加载的工具类,主要用于将样本数据划分为多个小批次(batch),以便进行训练、测试、验证等任务,查看模型脚本中的数据集加载方式是否是通过torch.utils.data.DataLoader加载,示例代码如下:

import torch
from torchvision import datasets, transforms
# 定义数据转换
transform = transforms.Compose([
    transforms.ToTensor(),  # 将图像转换为张量
    transforms.Normalize((0.5,), (0.5,))  # 标准化图像
])
# 加载MNIST数据集
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
# 创建数据加载器
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=4) 
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False, num_workers=4)
# 使用数据加载器迭代样本
for images, labels in train_loader:
    # 训练模型的代码
    ...

GPU单卡脚本迁移为NPU多卡脚本

如果迁移时启用了“distributed“参数,想将GPU单卡脚本迁移为NPU多卡脚本,需进行如下操作获取结果文件:

说明

将GPU单卡脚本迁移为NPU多卡脚本之后,若原模型训练命令中包含指定卡号进行单卡运行的参数(如--gpu),需要删除该参数,以确保多卡运行不失效。

  1. 训练脚本语句替换。

    将执行迁移命令后生成的“run_distributed_npu.sh“文件中的please input your shell script here语句替换成模型原来的训练shell脚本。例如将“please input your shell script here”替换为模型训练命令“bash_model_train_script.sh _--data_path data_path”。

    “run_distributed_npu.sh“文件如下所示:

    export MASTER_ADDR=127.0.0.1 
    export MASTER_PORT=29688 
    export HCCL_WHITELIST_DISABLE=1    
     
    NPUS=($(seq 0 7)) 
    export RANK_SIZE=${#NPUS[@]} 
    rank=0 
    for i in ${NPUS[@]} 
    do 
        export DEVICE_ID=${i} 
        export RANK_ID=${rank} 
        echo run process ${rank} 
        please input your shell script here > output_npu_${i}.log 2>&1 & 
        let rank++ 
    done
    

    表 7 run_distributed_npu.sh参数说明

    参数 说明
    MASTER_ADDR 指定训练服务器的IP。
    MASTER_PORT 指定训练服务器的端口。
    HCCL_WHITELIST_DISABLE HCCL通信白名单校验。
    NPUS 指定在特定NPU上运行。
    RANK_SIZE 指定调用卡的数量。
    DEVICE_ID 指定调用的device_id。
    RANK_ID 指定调用卡的逻辑ID。
  2. 替换后,执行“run_distributed_npu.sh“文件,会生成指定NPU的log日志。

  3. 查看结果文件。

    脚本迁移完成后,进入结果输出路径查看结果文件。以GPU单卡脚本迁移为NPU多卡脚本为例,结果文件包含以下内容:

    ├── xxx_msft/xxx_msft_multi         // 脚本迁移结果输出目录
    │   ├── 生成脚本文件                 // 与迁移前的脚本文件目录结构一致
    │   ├── msFmkTranspltlog.txt        // 脚本迁移过程日志文件,日志文件限制大小为1M,若超过限制将分多个文件进行存储,最多不会超过10个
    │   ├── cuda_op_list.csv            // 分析出的CUDA算子列表
    │   ├── unknown_api.csv             // 支持情况存疑的API列表
    │   ├── unsupported_api.csv         // 不支持的API列表
    │   ├── change_list.csv              // 修改记录文件
    │   ├── run_distributed_npu.sh       // 多卡启动shell脚本
    
  4. 查看迁移后的py脚本,可以看到脚本中的CUDA侧API被替换成NPU侧的API。

    def main():
        args = parser.parse_args()
     
        if args.seed is not None:
            random.seed(args.seed)
            torch.manual_seed(args.seed)
            cudnn.deterministic = True
            cudnn.benchmark = False
            warnings.warn('You have chosen to seed training. '
                          'This will turn on the CUDNN deterministic setting, '
                          'which can slow down your training considerably! '
                          'You may see unexpected behavior when restarting '
                          'from checkpoints.')
     
        if args.gpu is not None:
            warnings.warn('You have chosen a specific GPU. This will completely '
                          'disable data parallelism.')
     
        if args.dist_url == "env://" and args.world_size == -1:
            args.world_size = int(os.environ["WORLD_SIZE"])
     
        args.distributed = args.world_size > 1 or args.multiprocessing_distributed
     
        if torch_npu.npu.is_available():
            ngpus_per_node = torch_npu.npu.device_count()
        else:
            ngpus_per_node = 1
        if args.multiprocessing_distributed:
            # Since we have ngpus_per_node processes per node, the total world_size
            # needs to be adjusted accordingly
            args.world_size = ngpus_per_node * args.world_size
            # Use torch.multiprocessing.spawn to launch distributed processes: the
            # main_worker process function
            mp.spawn(main_worker, nprocs=ngpus_per_node, args=(ngpus_per_node, args))
        else:
            # Simply call main_worker function
            main_worker(args.gpu, ngpus_per_node, args)
    

FAQ

“Segmentation fault”错误

问题现象

运行转换后代码无报错,仅提示“Segmentation fault”信息。

原因分析

  • 可能原因一:

    代码中引用了TensorBoard或第三方库中包含TensorBoard,以下为已知的引用TensorBoard的第三方库。

    • wandb:若该库仅用来打log,可以删除该库的调用。
    • transformers:该库深度绑定TensorFlow、TensorBoard。
  • 可能原因二:

    训练脚本中包含两个0维Tensor在不同设备上进行比较的代码,当前该比较不支持在torch_npu上运行。

解决方案

  • 原因一解决方案:

    注释掉相关的Summary、Writer调用即可规避该错误。Summary、Writer多用于记录日志和绘图,不影响网络跑通和精度收敛。

  • 原因二解决方案:

    在脚本启动命令前添加python -X faulthandler打印线程信息,定位到具体的报错位置,进行pdb调试。来定位脚本中是否存在两个0维Tensor在不同设备上进行比较的代码,需要用户手动修改为在同一设备上进行比较,示例如下:

    修改前,在CPU和NPU上进行比较:

    a = torch.tensor(123)
    b = torch.tensor(456).npu()
    print(a == b)
    

    修改后,添加如下信息,修改为同在NPU上进行比较:

    a = torch.tensor(123).npu()
    b = torch.tensor(456).npu()
    print(a == b)
    

引用库找不到的问题

引用库找不到的问题,有可能是以下三种情况,请根据实际情况进行排查:

问题现象一
当前目录或子目录中存在的文件夹或者文件找不到引用库。

解决方案一
只需将该目录的父目录加到PYTHONPATH环境变量中即可。

问题现象二
找不到的引用库为requirements.txt中说明需要pip安装的包。

解决方案二
可以使用pip install 包名进行安装,若安装失败可以git clone安装包,使用python3 setup.py install安装。

问题现象三
找不到的引用库为readme.md中说明需要通过git clone下载安装的安装包。

解决方案三
请按照要求下载并安装。

Muls算子不支持int64

问题现象

解决方案
如上图所示,将label_batch.npu()改成label_batch.int().npu(),即把当前报错行的变量类型改成int32,规避此类Muls算子不支持int64的问题。

对于报错“No supported Ops kernel and engine are found for [ReduceStdV2A], optype [ReduceStdV2A]”,算子ReduceStdV2A不支持的问题

问题现象

报错“No supported Ops kernel and engine are found for [ReduceStdV2A], optype [ReduceStdV2A]”,算子ReduceStdV2A不支持。

解决方案
可以通过用std求标准差再平方得到var,均值单独调用mean接口求来规避问题例如:

具体到代码中修改:

常见运行报错

表 8 常见运行报错

报错信息 解决措施
运行报错:RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device(‘cpu’) to map your storages to the CPU. 一般在报错代码行加入参数map_location=torch.device(‘cpu’)即可规避此问题。
运行报错:Unsupport data type: at::ScalarType::Double. 在报错代码行前添加数据类型转换语句即可规避此问题。如报错代码行为pos = label.data.eq(1).nonzero(as_tuple =False).squeeze().npu()不支持数据类型,在代码上一行加上label = label.cpu().float().npu()进行数据类型转换。
运行报错:IndexError: invalid index of a 0-dim tensor. Use tensor.item() in Python or tensor.item() in C++ to convert a 0-dim tensor to a number. 遇到类似错误直接将代码中.data[0]改成.item()。例如将:M = (d_loss_real + torch.abs(diff)).data[0]改为:M = (d_loss_real + torch.abs(diff)).item()
运行报错:Could not run ‘aten::empty_with_format’ with arguments from the ‘CPUTensorId’ backend. ‘aten::empty_with_format’ is only available for these backend "CUDA、NPU". 需要将Tensor放到NPU上,类似input = input.npu()。
运行报错:options.device().type() == DeviceType::NPU INTERNAL ASSERT FAILED xxx: 需要将Tensor放到NPU上,类似input = input.npu()。
运行报错:Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. 此错误一般是torch.load()接口导致的,需要加关键字参数map_location,如map_location='npu’或map_location=‘cpu’。
运行报错:RuntimeError: Incoming model is an instance of torch.nn.parallel.DistributedDataParallel. Parallel wrappers should only be applied to the model(s) AFTER. 此错误是由于torch.nn.parallel.DistributedDataParallel接口在apex.amp.initial接口之前调用导致的,需要手动将torch.nn.parallel.DistributedDataParallel接口的调用移到apex.amp.initial接口调用之后即可。