Apprentissage distribué avec Apache MXNet et Horovod

La traduction de l'article a été préparée à la veille du début du cours "ML industriel sur le Big Data"

La formation distribuée sur plusieurs instances de calcul haute performance peut réduire le temps de formation des réseaux neuronaux profonds modernes sur de grandes quantités de données de plusieurs semaines à quelques heures, voire quelques minutes, ce qui rend cette technique de formation répandue dans les applications pratiques de l'apprentissage profond. Les utilisateurs doivent comprendre comment partager et synchroniser les données sur plusieurs instances, ce qui a un impact majeur sur l'efficacité de la mise à l'échelle. En outre, les utilisateurs doivent également savoir comment déployer un script de formation qui s'exécute sur une seule instance vers plusieurs instances.

Dans cet article, nous parlerons d'un moyen rapide et simple de distribuer l'apprentissage à l'aide de la bibliothèque ouverte d'apprentissage en profondeur Apache MXNet et du cadre d'apprentissage distribué Horovod. Nous démontrerons clairement les avantages en termes de performances du framework Horovod et montrerons comment écrire un script de formation MXNet afin qu'il fonctionne de manière distribuée avec Horovod.

Qu'est-ce qu'Apache MXNet

Apache MXNet est un cadre d'apprentissage profond open source utilisé pour créer, former et déployer des réseaux de neurones profonds. MXNet résume les complexités associées à la mise en œuvre de réseaux de neurones, est hautement performant et évolutif, et propose des API pour les langages de programmation populaires tels que Python, C + +, Clojure, Java, Julia, R, Scala et d'autres.

Formation distribuée en MXNet avec serveur de paramètres

Module d'apprentissage distribué standard dans MXNet utilise une approche de serveur de paramètres. Il utilise un ensemble de serveurs de paramètres pour collecter les dégradés de chaque travailleur, effectuer une agrégation et renvoyer les dégradés mis à jour aux travailleurs pour la prochaine itération d'optimisation. Déterminer le bon ratio serveurs/travailleurs est la clé d’une mise à l’échelle efficace. S’il n’y a qu’un seul serveur de paramètres, cela peut s’avérer être un goulot d’étranglement dans les calculs. À l’inverse, si trop de serveurs sont utilisés, la communication plusieurs-à-plusieurs peut obstruer toutes les connexions réseau.

Qu'est-ce que Horovod

Horovod est un cadre d'apprentissage profond distribué ouvert développé chez Uber. Il exploite des technologies efficaces entre GPU et entre nœuds telles que la bibliothèque de communications collectives NVIDIA (NCCL) et l'interface de transmission de messages (MPI) pour distribuer et agréger les paramètres du modèle entre les vorecs. Il optimise l'utilisation de la bande passante du réseau et s'adapte bien lorsque vous travaillez avec des modèles de réseaux neuronaux profonds. Il prend actuellement en charge plusieurs frameworks d'apprentissage automatique populaires, à savoir MXNet, Tensorflow, Keras et PyTorch.

Intégration MXNet et Horovod

MXNet s'intègre à Horovod via les API d'apprentissage distribué définies dans Horovod. API de communication Horovod horovod.broadcast(), horovod.allgather() и horovod.allreduce() implémenté à l'aide de rappels asynchrones du moteur MXNet, dans le cadre de son graphe de tâches. De cette manière, les dépendances de données entre la communication et le calcul sont facilement gérées par le moteur MXNet pour éviter les pertes de performances dues à la synchronisation. Objet optimiseur distribué défini dans Horovod horovod.DistributedOptimizer se développe Optimizer dans MXNet afin qu'il appelle les API Horovod correspondantes pour les mises à jour distribuées des paramètres. Tous ces détails de mise en œuvre sont transparents pour les utilisateurs finaux.

Départ rapide

Vous pouvez rapidement commencer à former un petit réseau neuronal convolutionnel sur l'ensemble de données MNIST à l'aide de MXNet et Horovod sur votre MacBook.
Tout d’abord, installez mxnet et horovod depuis PyPI :

pip install mxnet
pip install horovod

Remarque : Si vous rencontrez une erreur lors pip installer horovodpeut-être que tu dois ajouter une variable MACOSX_DEPLOYMENT_TARGET=10.vvvv – c’est la version de votre version MacOS, par exemple, pour MacOSX Sierra vous devrez écrire MACOSX_DEPLOYMENT_TARGET=10.12 pip installation horovod

Ensuite installez OpenMPI par conséquent,.

A la fin, téléchargez le script de test mxnet_mnist.py par conséquent, et exécutez les commandes suivantes dans le terminal MacBook dans le répertoire de travail :

mpirun -np 2 -H localhost:2 -bind-to none -map-by slot python mxnet_mnist.py

Cela exécutera une formation sur deux cœurs de votre processeur. Le résultat sera le suivant :

INFO:root:Epoch[0] Batch [0-50] Speed: 2248.71 samples/sec      accuracy=0.583640
INFO:root:Epoch[0] Batch [50-100] Speed: 2273.89 samples/sec      accuracy=0.882812
INFO:root:Epoch[0] Batch [50-100] Speed: 2273.39 samples/sec      accuracy=0.870000

Démo de performances

Lors de la formation d'un modèle ResNet50-v1 sur un ensemble de données ImageNet sur 64 GPU avec huit instances p3.16xlarge EC2, contenant chacun 8 GPU NVIDIA Tesla V100 sur le cloud AWS, nous avons atteint un débit d'entraînement de 45000 44 images/s (c'est-à-dire le nombre d'échantillons entraînés par seconde). Formation terminée en 90 minutes après 75.7 époques avec une meilleure précision de XNUMX %.

Nous avons comparé cela à l'approche de formation distribuée de MXNet consistant à utiliser des serveurs de paramètres sur 8, 16, 32 et 64 GPU avec un seul serveur de paramètres et un ratio serveur/travailleur de 1 pour 1 et 2 pour 1, respectivement. Vous pouvez voir le résultat dans la figure 1 ci-dessous. Sur l'axe des y à gauche, les barres représentent le nombre d'images à entraîner par seconde, les lignes reflètent l'efficacité de mise à l'échelle (c'est-à-dire le rapport entre le débit réel et le débit idéal) sur l'axe des y à droite. Comme vous pouvez le constater, le choix du nombre de serveurs affecte l’efficacité de la mise à l’échelle. S'il n'y a qu'un seul serveur de paramètres, l'efficacité de mise à l'échelle tombe à 38 % sur 64 GPU. Pour obtenir la même efficacité de mise à l'échelle qu'avec Horovod, vous devez doubler le nombre de serveurs par rapport au nombre de travailleurs.

Apprentissage distribué avec Apache MXNet et Horovod
Figure 1. Comparaison de l'apprentissage distribué utilisant MXNet avec Horovod et avec le serveur de paramètres

Dans le tableau 1 ci-dessous, nous comparons le coût final par instance lors de l'exécution d'expériences sur 64 GPU. L'utilisation de MXNet avec Horovod offre le meilleur débit au moindre coût.

Apprentissage distribué avec Apache MXNet et Horovod
Tableau 1. Comparaison des coûts entre Horovod et Parameter Server avec un ratio serveur/travailleur de 2 pour 1.

Étapes pour reproduire

Dans les prochaines étapes, nous vous montrerons comment reproduire le résultat d'une formation distribuée à l'aide de MXNet et Horovod. Pour en savoir plus sur l'apprentissage distribué avec MXNet, lisez ce post.

Étape 1

Créez un cluster d'instances homogènes avec MXNet version 1.4.0 ou supérieure et Horovod version 0.16.0 ou supérieure pour utiliser l'apprentissage distribué. Vous devrez également installer des bibliothèques pour la formation GPU. Pour nos instances, nous avons choisi Ubuntu 16.04 Linux, avec le pilote GPU 396.44, CUDA 9.2, la bibliothèque cuDNN 7.2.1, le communicateur NCCL 2.2.13 et OpenMPI 3.1.1. Vous pouvez également utiliser AMI Amazon Deep Learning, où ces bibliothèques sont déjà préinstallées.

Étape 2

Ajoutez la possibilité de travailler avec l'API Horovod à votre script de formation MXNet. Le script ci-dessous basé sur l'API MXNet Gluon peut être utilisé comme modèle simple. Les lignes en gras sont nécessaires si vous disposez déjà d’un script de formation correspondant. Voici quelques changements essentiels que vous devez apporter pour apprendre avec Horovod :

  • Définissez le contexte en fonction du rang Horovod local (ligne 8) pour comprendre que la formation est effectuée sur le bon noyau graphique.
  • Transmettez les paramètres initiaux d’un travailleur à tous (ligne 18) pour garantir que tous les travailleurs démarrent avec les mêmes paramètres initiaux.
  • Créer un Horovod Optimiseur distribué (ligne 25) pour mettre à jour les paramètres de manière distribuée.

Pour obtenir le script complet, veuillez vous référer aux exemples Horovod-MXNet MNIST и ImageNet.

1  import mxnet as mx
2  import horovod.mxnet as hvd
3
4  # Horovod: initialize Horovod
5  hvd.init()
6
7  # Horovod: pin a GPU to be used to local rank
8  context = mx.gpu(hvd.local_rank())
9
10 # Build model
11 model = ...
12
13 # Initialize parameters
14 model.initialize(initializer, ctx=context)
15 params = model.collect_params()
16
17 # Horovod: broadcast parameters
18 hvd.broadcast_parameters(params, root_rank=0)
19
20 # Create optimizer
21 optimizer_params = ...
22 opt = mx.optimizer.create('sgd', **optimizer_params)
23
24 # Horovod: wrap optimizer with DistributedOptimizer
25 opt = hvd.DistributedOptimizer(opt)
26
27 # Create trainer and loss function
28 trainer = mx.gluon.Trainer(params, opt, kvstore=None)
29 loss_fn = ...
30
31 # Train model
32 for epoch in range(num_epoch):
33    ...

Étape 3

Connectez-vous à l'un des travailleurs pour démarrer une formation distribuée à l'aide de la directive MPI. Dans cet exemple, la formation distribuée s'exécute sur quatre instances avec 4 GPU chacune et un total de 16 GPU dans le cluster. L'optimiseur de descente de gradient stochastique (SGD) sera utilisé avec les hyperparamètres suivants :

  • taille du mini-lot : 256
  • taux d'apprentissage : 0.1
  • élan : 0.9
  • perte de poids : 0.0001

Au fur et à mesure que nous sommes passés d'un GPU à 64 GPU, nous avons augmenté linéairement le taux de formation en fonction du nombre de GPU (de 0,1 pour 1 GPU à 6,4 pour 64 GPU), tout en gardant le nombre d'images par GPU à 256 (à partir d'un lot de 256 images pour 1 GPU à 16 384 pour 64 GPU). Les paramètres de perte de poids et d’élan ont changé à mesure que le nombre de GPU augmentait. Nous avons utilisé un entraînement de précision mixte avec le type de données float16 pour la passe avant et float32 pour les gradients afin d'accélérer les calculs float16 pris en charge par les GPU NVIDIA Tesla.

$ mpirun -np 16 
    -H server1:4,server2:4,server3:4,server4:4 
    -bind-to none -map-by slot 
    -mca pml ob1 -mca btl ^openib 
    python mxnet_imagenet_resnet50.py

Conclusion

Dans cet article, nous avons examiné une approche évolutive de la formation de modèles distribués à l'aide d'Apache MXNet et Horovod. Nous avons démontré l'efficacité de la mise à l'échelle et la rentabilité par rapport à l'approche du serveur de paramètres sur l'ensemble de données ImageNet sur lequel le modèle ResNet50-v1 a été formé. Nous avons également inclus des étapes que vous pouvez utiliser pour modifier un script existant afin d'exécuter une formation multi-instance à l'aide d'Horovod.

Si vous débutez avec MXNet et le deep learning, accédez à la page d'installation MXNepour construire d'abord MXNet. Nous vous recommandons également fortement de lire l'article MXNet en 60 minutespour commencer.

Si vous avez déjà travaillé avec MXNet et souhaitez essayer l'apprentissage distribué avec Horovod, jetez un œil à Page d'installation d'Horovod, construisez-le à partir de MXNet et suivez l'exemple MNIST ou ImageNet.

*le coût est calculé en fonction taux horaires AWS pour les instances EC2

En savoir plus sur le cours "ML industriel sur le Big Data"

Source: habr.com

Ajouter un commentaire