用于昇腾适配PyTorch框架,为使用PyTorch框架的开发者提供昇腾AI处理器的超强算力。
当前(2023.9.20)AscendPyTorch支持的pytorch版本如下:
AscendPyTorch版本 | CANN版本 | 支持PyTorch版本 | 代码分支名称 |
---|---|---|---|
5.0.RC2 | CANN 6.3.RC2 | 2.0.1.rc1 | v2.0.1-5.0.rc2 |
5.0.RC2 | CANN 6.3.RC2 | 1.8.1.post2 | v1.8.1-5.0.rc2 |
5.0.RC2 | CANN 6.3.RC2 | 1.11.0.post1 | v1.11.0-5.0.rc2 |
pytorch仓的结构:
简单而言,就是根据API调用时,输入的数据类型来决定后端调用的API类型。比如CPU和GPU的API是不一样的,可以自动根据传入的tensor类型来自动选择API。
具体来看,对于每一个前端的算子,dispatcher会维护一个函数指针表,为每个dispatch key提供对应的视线。这个表中有针对不同后端(CPU,GPU,XLA)的dispatch条目,也有想autograd和tracing这样的高抽象层级概念的条目。dispatcher根据输入的tensor和其他东西计算出一个dispatch key,然后跳转到函数指针表所指向的函数。
所以,对于昇腾处理器而言,实现Adapter主要就是要讲用昇腾实现的算子注册到dispatcher上面,即可复用pytorch的dispatch机制完成算子分布。
在线适配方案:模型执行,训练等主要功能流程有Pytorch框架提供,用户界面API保持不变,将Davinci设备和计算库作为扩展资源注册到PyTorch框架中。
模型迁移分为以下几步:
Ascend_Pytorch安装指南
方式一:利用torch的profiler来提取模型所用到的算子,然后查看NPU对这些算子的支持情况;
方式二:直接调用CANN分析迁移工具
```bash
python ms_fmk_transplt.py -i model_file.py -o model_file_out.py
```
其中ms_fmk_transplt.py已经包含在CANN安装包中了,默认路径为:/usr/local/Ascend/ascend-toolkit/latest/tools/ms_fmk_transplt/ms_fmk_transplt.py
。另外,该脚步还会输出迁移报告,里面有详细的不支持算子列表。
主要分:
主要修改点:
if torch.__version__ > 1.5:
import torch_npu
指定device类型为npu
device = torch.device("cuda:0") => device = torch.device("npu:0")
torch.cuda.set_device(device) => torch.npu.set_device(device)
tensor.to('cuda:0') => tensor.to('npu:0')
将训练脚步中的cuda接口替换为npu接口
torch.cuda.xxx() => torch.npu.xxx()
torch.cuda.set_device(0) => torch.npu.set_device(0)
torch.cuda.synchronize() => torch.npu.synchronize()
分布式代码迁移:将nccl
改为hccl
dist.init_process_group(backend='nccl', init_method='tcp://127.0.0.1:29688', world_size=8, rank=rank)
# 替换为:
dist.init_process_group(backend='hccl', init_method='tcp://127.0.0.1:29688', world_size=8, rank=rank)
注:Ascend pytorch只支持DDP,不支持DP。
ms_fmk_transplt.py
python ms_fmk_transplt.py -i model_file.py -o model_file_out.py
导入脚步转换库(支持PT1.8以上版本,推荐这种方式)
from torch_npu.contrib import transfer_to_npu
关于混合精度
# 方式一:torch.cuda.amp
use_amp = True
net = make_model(in_size, out_size, num_layers)
opt = torch.optim.SGD(net.parameters(), lr=0.001)
scaler = torch.cuda.amp.GradScaler(anabled_use_amp)
for epoch in range(epochs):
for input, target in zip(data, targets):
with torch.autocast(device_type='cuda', dtype=torch.float16, enabled=use_amp):
output = net(input)
loss = loss_fn(output, target)
scaler.scale(loss).backward()
scaler.step(opt)
scaler.update()
opt.zero_grad()
# 方式二:apex.amp
model = torch.nn.Linear(D_in, D_out).cuda()
optimzier = torch.optim.SGD(model.parameters(), lr=1e-3)
model, optimizer = amp.initialize(model, optimizer, opt_level='O1')
...
with amp.scale_loss(loss, optimizer) as scaled_loss:
scaled_loss.backward()
...