【Hello AI】使用AIACC-Training MXNet版

简介: 由于MXNet支持KVStore和Horovod两种分布式训练方式,因此AIACC-Training 1.5能够支持使用KVStore的方式对MXNet分布式训练进行加速,同时支持Horovod的分布式训练方式,并且能够无缝兼容Horovod的API版本。

由于MXNet支持KVStore和Horovod两种分布式训练方式,因此AIACC-Training 1.5能够支持使用KVStore的方式对MXNet分布式训练进行加速,同时支持Horovod的分布式训练方式,并且能够无缝兼容Horovod的API版本。

快速启用

代码适配与运行

适配AIACC-Training的方式与Horovod一致,如果您之前的训练代码是使用Horovod进行分布式训练,只需要替换import一行即可。替换内容如下:

import perseus.mxnet as hvd

示范用例

AIACC-Training软件包中为您提供了示例代码。您可以通过以下操作体验训练过程。

  1. 进入示例代码目录。
cd `echo $(python -c "import perseus; print(perseus)") | cut -d\' -f 4 | sed "s/\_\_init\_\_\.py//"`examples/
  1. 启动分布式训练。

以启动单机8卡的MNiST训练模型为例,示例命令如下:

perseusrun -np 8 -H localhost:8 python $examples_path/mxnet_mnist.py

适配MXNet

适配基于KVStore的API

为了支持InsightFace中特殊的数据+模型并行,Perseus KVStore增加了如下API:

  • local_rank:返回当前GPU worker在本节点内部的编号,以此编号来建立对应的gpu context。您可以在Python内部,直接使用local_rank作为当前的GPU ID来创建context,相较于在启动的Shell脚本中获得当前的GPU编号作为参数传入Python的示范用例,此方式更为便捷。
  • init(key_name, ndarray, param_only = false): init方法中增加参数param_only。取值说明如下:
  • true:表示其他参数的同步。当需要一次性同步如feature map数据、AllReduce精度数据等参数时,或者当不使用KVStore进行参数更新时,需要添加param_only参数并设置为true。
  • false:表示普通的梯度同步。
  • push(key_name, ndarray, op = PerseusOp.Sum):push方法中增加了用于同步Softmax layer的输出参数op。该参数的取值范围是Sum、Max、Min。默认值为Sum。
  1. 使用Perseus KVStore。

您需要参考如下示例修改自身训练代码,新增+后代码import perseus mxnet module,并删除-后代码,替换为KVStore的生成。示例如下:

diff --git a/example/image-classification/common/fit.py b/example/image-classification/common/fit.py
index 9412b6f..3a6e9a0 100755
--- a/example/image-classification/common/fit.py
+++ b/example/image-classification/common/fit.py
@@ -22,6 +22,7 @@ import time
 import re
 import math
 import mxnet as mx
+import perseus.mxnet as perseus_kv
 def _get_lr_scheduler(args, kv):
@@ -146,7 +147,8 @@ def fit(args, network, data_loader, **kwargs):
     # kvstore
-    kv = mx.kvstore.create(args.kv_store)
+    kv = perseus_kv.create(args.kv_store) if args.kv_store == dist_sync_perseus else mx.kvstore.create(args.kv_store)
     if args.gc_type != 'none':
         kv.set_gradient_compression({'type': args.gc_type,
                                      'threshold': args.gc_threshold})
  1. 将进程绑定至GPU卡。

AIACC-Training通过重载KVStore实现了对MXNet分布式训练的支持,在API上与原生KVStore基本兼容,使用AIACC-Training后,您只需要对模型代码中的ctx设定稍作修改,将单进程绑定至单张GPU卡上即可。

以如下代码片段为例,使用Perseus KVStore新增的API local_rank,将当前process绑定到kv.local_rank所对应的GPU卡上。

ctx = []
cvd = os.environ['DEVICES'].strip()
if 'perseus' in args.kv_store:
    import perseus.mxnet as perseus
    ctx.append(mx.gpu(kv.local_rank))
  1. 启动分布式训练任务。

与其它框架类似,Perseus采用MPI的启动方式,并且启动单机多卡与多机多卡的方式基本一致,不再支持原生MXNet下的单机多卡在单一Process中的模式。以下操作以启动4机8卡分布式训练任务为例,带您体验启动过程。

  1. 准备训练脚本config.sh

由于该脚本要使用mpirun命令运行,因此需要使用MPI的环境变量来推导此进程所对应的GPU设备ID,然后设定此环境变量,并将此ID作为参数传递到module代码中去创建对应的ctx。脚本示例如下:

#!/bin/sh
let GPU=OMPI_COMM_WORLD_RANK % OMPI_COMM_WORLD_LOCAL_SIZE
export OMP_NUM_THREADS=4
MXNET_VISIBLE_DEVICE=$GPU python train_imagenet.py \
                                 --network resnet \
                                 --num-layers 50 \
                                 --kv-store dist_sync_perseus \
                                 --gpus $GPU …
  1. 执行如下命令,启动训练脚本。
mpirun -np 32 -npernode 8 -hostfile mpi_host.txt  ./config.sh

其中,mpi_host.txt为普通的MPI machinefile,与MXNet的SSHLauncher的host file类似,简单示例如下:

192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4

开始训练之后,每个GPU都是一个单独的进程,有各自的输出。查看多机情况下每个机器的输出,总性能为所有单进程性能的总和。

开源版本MXNet会默认占据系统所有的CPU资源,因此在最初的启动阶段,会占用较多的CPU时间,启动速度较慢。您可以通过设置以下环境变量解决该问题。

export MXNET_USE_OPERATOR_TUNING=0
export MXNET_USE_NUM_CORES_OPERATOR_TUNING=1
export OMP_NUM_THREADS=1

适配基于Horovod的API

本小节介绍如何使用Horovod兼容API进行MXNet分布式训练的基本步骤,以下操作为原始训练代码适配到AIACC-Traninig的一般过程。

AIACC-Training for MXNet支持Horovod API。适配AIACC-Training的方式与Horovod一致,如果您之前是使用Horovod进行分布式训练,只需替换import模块即可。替换后的内容如下:

import perseus.mxnet as hvd

如果您的训练代码是非分布式代码,可以参考以下操作步骤将训练代码升级为Horovod接口的分布式训练代码。

  1. 在main函数的开头部分,执行如下命令,初始化Perseus Horovod模块。

说明:请务必在使用其他Perseus API之前进行调用。

hvd.init()
  1. 将当前进程绑定对应的GPU卡。
# rank and size
rank = hvd.rank()
num_workers = hvd.size()
local_rank = hvd.local_rank()
# Horovod: pin GPU to local rank
context = mx.gpu(local_rank)
  1. 创建Optimizer。

通常情况下,模型的学习率需要增大hvd.size()倍。

说明:部分模型不需要增大学习率,如BERT模型,具体请根据训练收敛情况作判断。

learning_rate = ...
optimizer_params = {'learning_rate': learning_rate * hvd.size()}
opt = mx.optimizer.create(optimizer, **optimizer_params)
  1. 广播参数。
# Horovod: fetch and broadcast parameters
params = net.collect_params()
if params is not None:
    hvd.broadcast_parameters(params)
  1. 重载Optimizer。
# Horovod: create DistributedTrainer, a subclass of gluon.Trainer
trainer = hvd.DistributedTrainer(params, opt)
  1. 启动训练。

以4机8卡的训练为例,启动命令示例如下:

mpirun -np 32 -npernode 8 -hostfile mpi_host.txt  ./train.sh

其中,mpi_host.txt为普通的MPI machinefile,与MXNet的SSHLauncher的host file类似,简单示例如下:

192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4

开始训练之后,每个GPU都是一个单独的进程,有各自的输出。类比多机情况下每个机器的输出,总性能为所有单process性能的总和。

使用SyncBatchNorm

Perseus的SyncBatchNorm实现基于MXNet官方代码src/operator/contrib/sync_batch_norm-inl.h的计算逻辑,并通过加载libperseus_MXNet.so调用Perseus通信的API,在operator内部实现SyncBatchNorm,且支持单机local模式以及全局global模式。

背景信息

针对object-detection等小Batch Size场景,继续使用每个GPU单独的BatchNorm计算的mean和var信息有较大的偏差,会带来一定的精度损失。通过使用SyncBatchNorm可以弥补对统计信息的内部偏移,真正发挥理论上BN层的作用,即使在大规模分布式的情况下也能达到更高的期望精度。相较于原始BatchNorm,SyncBatchNorm能够在忽略某些训练性能的情况下,提高收敛精度的上限。

操作步骤

  1. 使用perseus-MXNet-sync-bn.patch补丁。
patch -p1 < perseus-mxnet-sync-bn.patch
  1. 编译MXNet源码。
make USE_OPENCV=1 USE_BLAS=openblas USE_CUDA=1 USE_CUDA_PATH=/usr/local/cuda USE_CUDNN=1 USE_DIST_KVSTORE=1 USE_NCCL=1 USE_LIBJPEG_TURBO=1 MPI_ROOT=/usr/local -j24
  1. 调用SyncBatchNorm模型。

Perseus的SyncBatchNorm实现基于原始MXNet官方代码,因此兼容SyncBatchNorm的原始使用方法,只需将名称从SyncBatchNorm修改为PerseusSyncBatchNorm,并增加参数comm_scope用于修改模式,如mx.gluon.contrib.nn.PerseusSyncBatchNorm(comm_scope=0), mx.sym.contrib.PerseusSyncBatchNorm(comm_scope=0)

  1. 修改模式。

模式说明如下:

  • local:局部平均,即每次forward、backward计算均值和方差后,只在单机内部的GPU上分别进行同步。默认为此模式,参数设置为PerseusSyncBatchNorm(comm_scope=0)。
  • global:全局平均,即每次forward、backward计算的均值和方差在全局进行同步,需要修改BN定义的参数为PerseusSyncBatchNorm(comm_scope=1)。

测试精度

以单卡Batch Size为2,单机8卡的训练为例,使用基于GluonCV实现的Faster RCNN模型适配Perseus,然后进行原始BatchNorm与PerseusSyncBatchNorm的精度对比,测试效果图如下:

如上图所示,从第1个Epoch开始,到第20个Epoch结束,PerseusSyncBatchNorm达到的精度均高于BatchNorm,最高的mAP从31.3%提升至34.6%。

常见问题

额外显存占用问题

以单机8卡为例,0号卡被其余7个process均占用了200 MB到500 MB显存,从而导致0号卡显存被耗尽。

该问题的根因在于MXNet内部的cpu_pinned memory分配机制默认使用0号卡。您可以参考上文步骤2,重新绑定GPU卡。

运行时显示Undefined symbols

运行时显示NDArray相关的symbol没有定义,即Undefined symbols

该问题由于pip安装了1.4之前版本的MXNet,导致没有导出libMXNet.so中对于Perseus必要的symbol。您可以将MXNet升级到1.4或以上版本,也可以重新编译安装MXNet。

启动速度较慢

您可以尝试以下方法改善该问题:

  • 检查CPU的负载,若占比很高可尝试进行以下设置:
export MXNET_USE_OPERATOR_TUNING=0
export MXNET_USE_NUM_CORES_OPERATOR_TUNING=1
export OMP_NUM_THREADS=1
  • 减小preprocess的线程数。

Perseus下训练模式为单process、单GPU,如果默认线程数设置过大,可以根据单节点的GPU数目,等比例缩小preprocess的线程数。例如preprocess的线程数默认值为24,而单节点GPU数目为8,那么您可以将preprocess的线程数降低为3或4。

单机时正常,多机时异常退出

可能是由于人为导致多机中存在正在运行训练的机器,则运行多机会发生create cusolver handle failed报错,您可以使用mpirun执行nvidia-smi检查多机中是否存在运行的机器。


好啦!小弹的分享到此为止。我们更欢迎您分享您对阿里云产品的设想、对功能的建议或者各种吐槽,请扫描提交问卷并获得社区积分或精美礼品一份。https://survey.aliyun.com/apps/zhiliao/P4y44bm_8

【扫码填写上方调研问卷】

欢迎每位来到弹性计算的开发者们来反馈问题哦~

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
6月前
|
人工智能 弹性计算 自然语言处理
【Hello AI】AIACC-ACSpeed性能数据
本文展示了AIACC-ACSpeed的部分性能数据,相比较通过原生DDP训练模型后的性能数据,使用AIACC-ACSpeed训练多个模型时,性能具有明显提升。
|
6月前
|
人工智能 弹性计算 PyTorch
【Hello AI】安装和使用Deepytorch-面向生成式AI和大模型场景
Deepytorch是阿里云自研的AI加速器,面向生成式AI和大模型场景,提供了显著的训练和推理加速能力。本文主要介绍安装并使用Deepytorch的操作方法。
|
6月前
|
人工智能 并行计算 PyTorch
【Hello AI】手动安装AIACC-Inference(AIACC推理加速)Torch版
AIACC-Inference(AIACC推理加速)支持优化基于Torch框架搭建的模型,能够显著提升推理性能。本文介绍如何手动安装AIACC-Inference(AIACC推理加速)Torch版并提供示例体验推理加速效果。
|
6月前
|
TensorFlow 调度 算法框架/工具
【Hello AI】通过Docker安装并使用cGPU服务
cGPU服务可以隔离GPU资源,实现多个容器共用一张GPU卡。该服务作为阿里云容器服务Kubernetes版ACK(Container Service for Kubernetes)的组件对外提供服务,本文介绍如何通过Docker安装并使用cGPU服务。
|
6月前
|
PyTorch 算法框架/工具 异构计算
【Hello AI】安装并使用DeepGPU-LLM-处理大语言模型任务
在处理大语言模型任务中,您可以根据实际业务部署情况,选择在不同环境(例如GPU云服务器环境或Docker环境)下安装推理引擎DeepGPU-LLM,然后通过使用DeepGPU-LLM工具实现大语言模型(例如Llama模型、ChatGLM模型、百川Baichuan模型或通义千问Qwen模型)在GPU上的高性能推理优化功能
|
6月前
|
人工智能 JavaScript 前端开发
【AI大模型应用开发】【LangChain系列】0. LangChain框架介绍,实现LangChain的Hello World
【AI大模型应用开发】【LangChain系列】0. LangChain框架介绍,实现LangChain的Hello World
139 0
|
6月前
|
并行计算 Linux 文件存储
【Hello AI】安装并使用FastGPU-命令行使用说明
用户可以通过FastGPU的命令行,快速地部署云上GPU集群,管理资源的生命周期。还可以便捷地为集群安装深度学习环境,在集群运行代码,查看运行日志以及释放资源。
|
6月前
|
人工智能 弹性计算 固态存储
【Hello AI】AIACC-AGSpeed性能数据
本文展示了AIACC-AGSpeed(简称AGSpeed)的部分性能数据,相比较通过PyTorch原生Eager模式训练模型后的性能数据,使用AGSpeed训练多个模型时,性能具有明显提升。
|
6月前
|
机器学习/深度学习 人工智能 PyTorch
【Hello AI】安装和使用AIACC-AGSpeed(优化PyTorch深度学习模型)
AIACC-AGSpeed(简称AGSpeed)专注于优化PyTorch深度学习模型在阿里云GPU异构计算实例上的计算性能,相比原始的神龙AI加速引擎AIACC,可以实现无感的计算优化性能。本文为您介绍安装和使用AGSpeed的方法。
|
6月前
|
人工智能 弹性计算 测试技术
【Hello AI】AIACC-ACSpeed体验示例
AIACC-ACSpeed(简称ACSpeed)作为阿里云自研的AI训练加速器,在提高训练效率的同时能够降低使用成本,可以实现无感的分布式通信性能优化。ACSpeed软件包中已为您提供了适配DDP的示例代码,您可以参考本文快速体验使用ACSpeed进行模型分布式训练的过程以及性能提升效果。