【2023 · CANN训练营第一季】PyTorch模型迁移之迁移流程
收藏回复举报
【2023 · CANN训练营第一季】PyTorch模型迁移之迁移流程
发表于2023-05-31 20:53:01
0 查看

PyTorch模型迁移指导

cke_2187.png

算子满足度分析

方式一:使用PyTorch profiler在GPU上提取算子

  1. 在模型训练脚本中使能torch.autograd.profiler功能,这里record_shapes必须设置为True,在GPU上使用use_cuda设置为True,row_limit表示模型中算子总数(可重复),需要设置足够大。

    cke_5876.png

  2. 运行训练脚本并将打屏日志重定向到文件中

    # 执行命令示例python3.7 train.py > profiler.log
  3. 使用算子提取工具解析日志,提取API

    # 执行命令示例python extract_ops_by_step.py --profiler_file ./prof.log

cke_10793.png

方式二:使用CANN分析迁移工具

  1. 使用脚本转换工具,将GPU训练脚本转换为NPU脚本

    python3 ms_fmk_transplt.py -i 原始脚本路径 -o 脚本转换结果输出路径
  2. 查看迁移报告中的不支持算子列表

    cke_14739.png

在迁移前,如果不进行评估的话,也可以在后续使用脚本转换工具进行自动迁移时,通过生成的迁移报告,获取不支持的API,但通过三方库调用torch API的场景无法收集。

准备昇腾软硬件环境

cke_18594.png

模型迁移的方式

目前有三种迁移方式,自动迁移、工具迁移、手工迁移。

自动迁移是训练时,在训练脚本中导入脚本转换库,运行训练脚本时,先自动将PyTorch训练脚本中的cuda接口更换为对应昇腾AI处理器支持的接口,再进行训练。操作简洁。

工具迁移是训练前,通过迁移脚本转换工具,自动将PyTorch训练脚本中的cuda接口更换为对应的昇腾AI处理器支持的接口,生成一套昇腾AI处理器上的训练脚本,同时生成迁移报告(脚本转换过程日志、不支持算子列表、脚本修改记录),训练时,直接运行迁移后的训练脚本。迁移过程记录详细。

手动迁移是算法工程师通过自行修改PyTorch训练脚本,以支持在昇腾AI处理器上执行训练。

自动迁移

仅PyTorch 1.8.1版本及以上使用,自动迁移方式较简单,且修改内容最少,只需在训练脚本中添加引入库代码。

import torch
import torch_npu
.....
from torch_npu.contrib import transfer_to_npu

执行训练脚本时,在模型训练前,自动替换训练脚本中的昇腾AI处理器不支持的接口:

cke_22762.png

工具迁移

cke_26949.png

基于mindstudio可视化迁移:link

手动迁移

具体查看NPU对PyTorch API支持度清单

关键修改点如下:

单卡迁移

  1. 导入NPU相关库(PyTorch版本1.8及以上时需要导入) 。

    if torch.__version__ > 1.5:      
    import torch_npu
  2. 指定device类型为npu。

    #修改前
    device = torch.device('cuda:0')
    torch.cuda.set_device(device)
    tensor.to('cuda:0')
    #修改后
    device = torch.device('npu:0')
    torch.npu.set_device(device)
    tensor.to('npu:0')
  3. 将训练脚本中的cuda接口替换为NPU接口。

    #修改前
    torch.cuda.xxx()
    torch.cuda.set_device(0)
    torch.cuda.synchronize()
    #修改后
    torch.npu.xxx()
    torch.npu.set_device(0)
    torch.npu.synchronize()

多卡迁移

昇腾只支持DDP模式,不支持DP模式;支持单机多卡、多机多卡训练,使用方式与原生PyTorch相同。除了单Device迁移的修改点,在分布式场景下,还涉及如下关键修改点如下:

  • 将“nccl”改为“hccl”,使用NPU的HCCL集合通信库进行分布式训练。
  • 修改init_process_group接口的参数,支持直接修改或设置环境变量两种方式,如下所示。
    • 方式1:通过接口设置

      dist.init_process_group(backend=‘hccl’, 
      init_method=“tcp://127.0.0.1:29688”,
      world_size=args.world_size, rank=args.rank)
    • 方式2:通过环境变量设置

      os.environ['MASTER_ADDR'] = ‘127.0.0.1’ 
      os.environ['MASTER_PORT'] = '29688'
      dist.init_process_group(backend=‘hccl’,world_size=args.world_size, rank=args.rank)

关于混合精度

cke_31564.png

CUBE仅支持FP16,对于FP32的矩阵运算,无法调用CUBE的高算力,框架调用Vector算子,性能差距明显;而卷积算子,由于Vector不支持,会强制走FP16,可能带来梯度消失的问题,整网使用FP16,数值范围小,容易导致梯度消失,自动混合精度(AMP),通过梯度scale以及回落FP32消除FP16的影响。

昇腾支持两种amp方式:

  1. torch.cuda.amp

    cke_36847.png

  2. apex.amp

    cke_39938.png

Amp本身是性能优化,但在npu上不用amp后果不可控(卷积强制走fp16,可能梯度消失),故是必须动作。

我要发帖子