Apache MXNet - Formation distribuée

Ce chapitre concerne la formation distribuée dans Apache MXNet. Commençons par comprendre quels sont les modes de calcul dans MXNet.

Modes de calcul

MXNet, une bibliothèque ML multilingue, offre à ses utilisateurs les deux modes de calcul suivants:

Mode impératif

Ce mode de calcul expose une interface comme l'API NumPy. Par exemple, dans MXNet, utilisez le code impératif suivant pour construire un tenseur de zéros à la fois sur le processeur et le GPU -

import mxnet as mx
tensor_cpu = mx.nd.zeros((100,), ctx=mx.cpu())
tensor_gpu= mx.nd.zeros((100,), ctx=mx.gpu(0))

Comme nous le voyons dans le code ci-dessus, MXNets spécifie l'emplacement où se trouve le tenseur, dans le processeur ou le périphérique GPU. Dans l'exemple ci-dessus, il se trouve à l'emplacement 0. MXNet réalise une utilisation incroyable de l'appareil, car tous les calculs se font paresseusement au lieu d'être instantanément.

Mode symbolique

Bien que le mode impératif soit assez utile, mais l'un des inconvénients de ce mode est sa rigidité, c'est-à-dire que tous les calculs doivent être connus au préalable avec des structures de données prédéfinies.

D'autre part, le mode symbolique expose un graphe de calcul comme TensorFlow. Il supprime l'inconvénient de l'API impérative en permettant à MXNet de travailler avec des symboles ou des variables au lieu de structures de données fixes / prédéfinies. Ensuite, les symboles peuvent être interprétés comme un ensemble d'opérations comme suit -

import mxnet as mx
x = mx.sym.Variable(“X”)
y = mx.sym.Variable(“Y”)
z = (x+y)
m = z/100

Types de parallélisme

Apache MXNet prend en charge la formation distribuée. Cela nous permet d'exploiter plusieurs machines pour une formation plus rapide et efficace.

Voici les deux façons dont nous pouvons répartir la charge de travail de la formation d'un NN sur plusieurs appareils, CPU ou GPU -

Parallélisme des données

Dans ce type de parallélisme, chaque appareil stocke une copie complète du modèle et fonctionne avec une partie différente de l'ensemble de données. Les appareils mettent également à jour un modèle partagé collectivement. Nous pouvons localiser tous les appareils sur une seule machine ou sur plusieurs machines.

Parallélisme de modèle

C'est un autre type de parallélisme, qui est pratique lorsque les modèles sont si volumineux qu'ils ne rentrent pas dans la mémoire de l'appareil. Dans le parallélisme de modèle, différents périphériques se voient attribuer la tâche d'apprendre différentes parties du modèle. Le point important à noter ici est qu'actuellement, Apache MXNet prend en charge le parallélisme de modèle sur une seule machine.

Fonctionnement de la formation distribuée

Les concepts donnés ci-dessous sont la clé pour comprendre le fonctionnement de la formation distribuée dans Apache MXNet -

Types de processus

Les processus communiquent entre eux pour accomplir la formation d'un modèle. Apache MXNet a les trois processus suivants -

Ouvrier

Le travail du nœud de travail consiste à effectuer la formation sur un lot d'échantillons de formation. Les nœuds de travail extrairont les poids du serveur avant de traiter chaque lot. Les nœuds Worker enverront des dégradés au serveur, une fois le lot traité.

Serveur

MXNet peut avoir plusieurs serveurs pour stocker les paramètres du modèle et communiquer avec les nœuds de travail.

Planificateur

Le rôle du planificateur est de configurer le cluster, ce qui inclut l'attente des messages que chaque nœud est arrivé et quel port le nœud écoute. Après avoir configuré le cluster, le planificateur informe tous les processus de chaque autre nœud du cluster. C'est parce que les processus peuvent communiquer entre eux. Il n'y a qu'un seul planificateur.

Magasin KV

KV stores signifie Key-Valueboutique. C'est un composant essentiel utilisé pour la formation multi-appareils. Il est important car la communication des paramètres entre les appareils sur une seule ou plusieurs machines est transmise via un ou plusieurs serveurs avec un KVStore pour les paramètres. Comprenons le fonctionnement de KVStore à l'aide des points suivants -

  • Chaque valeur dans KVStore est représentée par un key et un value.

  • Chaque tableau de paramètres du réseau se voit attribuer un key et les poids de ce tableau de paramètres sont référencés par value.

  • Après cela, les nœuds de travail pushdégradés après le traitement d'un lot. Ils aussipull poids mis à jour avant de traiter un nouveau lot.

La notion de serveur KVStore n'existe que pendant l'entraînement distribué et le mode distribué de celui-ci est activé en appelant mxnet.kvstore.create fonction avec un argument chaîne contenant le mot dist -

kv = mxnet.kvstore.create(‘dist_sync’)

Distribution des clés

Il n'est pas nécessaire que tous les serveurs stockent tous les paramètres du tableau ou des clés, mais ils sont répartis sur différents serveurs. Une telle distribution de clés sur différents serveurs est gérée de manière transparente par le KVStore et la décision de savoir quel serveur stocke une clé spécifique est prise au hasard.

KVStore, comme indiqué ci-dessus, garantit que chaque fois que la clé est tirée, sa demande est envoyée à ce serveur, qui a la valeur correspondante. Et si la valeur d'une clé est élevée? Dans ce cas, il peut être partagé entre différents serveurs.

Diviser les données d'entraînement

En tant qu'utilisateurs, nous voulons que chaque machine travaille sur différentes parties de l'ensemble de données, en particulier, lors de l'exécution d'un entraînement distribué en mode parallèle de données. Nous savons que, pour diviser un lot d'échantillons fournis par l'itérateur de données pour l'entraînement en parallèle des données sur un seul travailleur, nous pouvons utilisermxnet.gluon.utils.split_and_load puis, chargez chaque partie du lot sur l'appareil qui le traitera davantage.

D'un autre côté, en cas de formation distribuée, au début, nous devons diviser l'ensemble de données en ndifférentes parties de sorte que chaque travailleur obtient une partie différente. Une fois obtenu, chaque travailleur peut alors utilisersplit_and_loadpour diviser à nouveau cette partie de l'ensemble de données entre différents appareils sur une seule machine. Tout cela se passe par l'itérateur de données.mxnet.io.MNISTIterator et mxnet.io.ImageRecordIter sont deux de ces itérateurs dans MXNet qui prennent en charge cette fonctionnalité.

Mise à jour des poids

Pour mettre à jour les poids, KVStore prend en charge les deux modes suivants -

  • La première méthode regroupe les gradients et met à jour les poids en utilisant ces gradients.

  • Dans la seconde méthode, le serveur agrège uniquement les dégradés.

Si vous utilisez Gluon, il existe une option pour choisir entre les méthodes indiquées ci-dessus en passant update_on_kvstorevariable. Comprenons-le en créant letrainer objet comme suit -

trainer = gluon.Trainer(net.collect_params(), optimizer='sgd',
   optimizer_params={'learning_rate': opt.lr,
      'wd': opt.wd,
      'momentum': opt.momentum,
      'multi_precision': True},
      kvstore=kv,
   update_on_kvstore=True)

Modes de formation distribuée

Si la chaîne de création KVStore contient le mot dist, cela signifie que la formation distribuée est activée. Voici différents modes de formation distribuée qui peuvent être activés en utilisant différents types de KVStore -

dist_sync

Comme son nom l'indique, il désigne un entraînement distribué synchrone. En cela, tous les travailleurs utilisent le même ensemble synchronisé de paramètres de modèle au début de chaque lot.

L'inconvénient de ce mode est qu'après chaque lot, le serveur doit attendre de recevoir des dégradés de chaque worker avant de mettre à jour les paramètres du modèle. Cela signifie que si un travailleur tombe en panne, cela arrêtera la progression de tous les travailleurs.

dist_async

Comme son nom l'indique, il désigne un entraînement distribué synchrone. En cela, le serveur reçoit des dégradés d'un travailleur et met immédiatement à jour son magasin. Le serveur utilise le magasin mis à jour pour répondre à toute autre extraction.

L'avantage, par rapport à dist_sync mode, est qu'un travailleur qui termine le traitement d'un lot peut extraire les paramètres actuels du serveur et démarrer le lot suivant. Le travailleur peut le faire, même si l'autre travailleur n'a pas encore terminé le traitement du lot précédent. Il est également plus rapide que le mode dist_sync car il peut prendre plus d'époques pour converger sans aucun coût de synchronisation.

dist_sync_device

Ce mode est le même que dist_syncmode. La seule différence est que, lorsque plusieurs GPU sont utilisés sur chaque nœuddist_sync_device agrège les gradients et met à jour les poids sur le GPU alors que, dist_sync agrège les gradients et met à jour les poids sur la mémoire du processeur.

Cela réduit les communications coûteuses entre le GPU et le CPU. C'est pourquoi, c'est plus rapide quedist_sync. L'inconvénient est qu'il augmente l'utilisation de la mémoire sur le GPU.

dist_async_device

Ce mode fonctionne de la même manière que dist_sync_device mode, mais en mode asynchrone.