MXNet/fr
MXNet est une bibliothèque d'apprentissage profond à la fois souple et efficace, qui permet de combiner la programmation symbolique et impérative pour maximiser l'efficacité et la productivité. À la base, MXNet intègre un ordonnanceur de dépendances dynamique qui parallélise automatiquement les opérations symboliques et impératives au fur et à mesure de leur apparition. Une couche d'optimisation des graphes de niveau supérieur rend l'exécution symbolique rapide et économe en mémoire. MXNet est portable, léger et évolutif pour de nombreux GPU et machines.
Paquets disponibles¶
Pour savoir quels paquets sont offerts, utilisez la commande avail_wheels.
name version python arch
------ --------- -------- ------
mxnet 1.9.1 cp39 avx2
mxnet 1.9.1 cp38 avx2
mxnet 1.9.1 cp310 avx2
Installation dans un environnement virtuel Python¶
-
Créez et activez un environnement virtuel Python.
-
Installez MXNet et ses dépendances Python.
-
Validation de l'installation.
Exécution d'une tâche¶
-
Exemple de couche de convolution simple :
mxnet-conv-ex.py#!/bin/env python import mxnet as mx import numpy as np num_filter = 32 kernel = (3, 3) pad = (1, 1) shape = (32, 32, 256, 256) x = mx.sym.Variable('x') w = mx.sym.Variable('w') y = mx.sym.Convolution(data=x, weight=w, num_filter=num_filter, kernel=kernel, no_bias=True, pad=pad) device = mx.gpu() if mx.context.num_gpus() > 0 else mx.cpu() # On CPU will use MKLDNN, or will use cuDNN exe = y.simple_bind(device, x=shape) exe.arg_arrays[0][:] = np.random.normal(size=exe.arg_arrays[0].shape) exe.arg_arrays[1][:] = np.random.normal(size=exe.arg_arrays[1].shape) exe.forward(is_train=False) o = exe.outputs[0] t = o.asnumpy() print(t) -
Modifiez le script ci-dessous selon les besoins de votre tâche.
mxnet-conv.sh#!/bin/bash #SBATCH --job-name=mxnet-conv #SBATCH --account=def-someprof # ajustez ceci pour correspondre au groupe de calcul que vous utilisez #SBATCH --time=01:00:00 # ajustez ceci pour correspondre à la durée d'exécution demandée pour votre tâche #SBATCH --cpus-per-task=2 # ajustez ceci pour correspondre au nombre de cœurs #SBATCH --mem=20G # ajustez ceci en fonction de la mémoire dont vous avez besoin # Chargement des dépendances des modules module load python/3.10 # Générez votre environnement virtuel dans $SLURM_TMPDIR virtualenv --no-download ${SLURM_TMPDIR}/env source ${SLURM_TMPDIR}/env/bin/activate # Installez MXNet et ses dépendances pip install --no-index mxnet==1.9.1 # Utilisera MKLDNN python mxnet-conv-ex.pymxnet-conv.sh#!/bin/bash #SBATCH --job-name=mxnet-conv #SBATCH --account=def-someprof # ajustez ceci pour correspondre au groupe de calcul que vous utilisez #SBATCH --time=01:00:00 # ajustez ceci pour correspondre à la durée d'exécution demandée pour votre tâche #SBATCH --cpus-per-task=2 # ajustez ceci pour correspondre au nombre de cœurs #SBATCH --mem=20G # ajustez ceci en fonction de la mémoire dont vous avez besoin #SBATCH --gres=gpu:1 # ajustez ceci pour correspondre au nombre de GPU, sauf pour l'entraînement distribué, utilisez 1 # Chargement des dépendances des modules module load python/3.10 # Générez votre environnement virtuel dans $SLURM_TMPDIR virtualenv --no-download ${SLURM_TMPDIR}/env source ${SLURM_TMPDIR}/env/bin/activate # Installez MXNet et ses dépendances pip install --no-index mxnet==1.9.1 # Utilisera cuDNN python mxnet-conv-ex.py -
Soumettez la tâche à l'ordonnanceur SLURM.
Optimisation des performances¶
Utiliser plusieurs CPU ou un seul GPU¶
Utilisation des ressources
À l'instar de PyTorch et TensorFlow, MXNet propose des implémentations similaires d'opérateurs pour les CPU et les GPU, incluant les multiplications matricielles et les convolutions, que ce soit avec OpenMP et MKLDNN (pour les CPU) ou CUDA et cuDNN (pour les GPU). Que votre code effectue ou non ces opérations, elles utiliseront automatiquement le mode multithread sur plusieurs cœurs de CPU ou un GPU si la tâche le requiert.
Cela dit, nous vous encourageons fortement à privilégier l'utilisation de plusieurs CPU plutôt qu'un seul GPU. Si votre modèle et votre ensemble de données ne sont pas assez grands, l'entraînement sera certainement plus rapide avec un GPU (sauf pour de très petits modèles), mais la différence de vitesse par rapport aux CPU ne sera pas significative, et la tâche n'utilisera qu'un faible pourcentage de la capacité de calcul du GPU. Ce n'est peut-être pas un problème pour votre ordinateur personnel, mais dans un environnement partagé comme nos grappes de calcul, vous bloquez sans raison valable une ressource qui pourrait être utilisée par d'autres pour effectuer des calculs à grande échelle. De plus, vous consommez l'allocation de votre groupe de calcul et avez un effet négatif sur la priorité accordée aux tâches de vos collègues.
Autrement dit, ne demandez pas un GPU si votre code est incapable de faire un usage raisonnable de sa capacité de calcul. L'exemple suivant montre l'entraînement d'un réseau neuronal convolutif avec ou sans GPU.
#!/bin/bash
#SBATCH --nodes 1
#SBATCH --tasks-per-node=1
#SBATCH --cpus-per-task=1 # change this parameter to 2,4,6,... to see the effect on performance
#SBATCH --gres=gpu:1 # Remove this line to run using CPU only
#SBATCH --mem=8G
#SBATCH --time=0:05:00
#SBATCH --output=%N-%j.out
#SBATCH --account=<your account>
module load python # Using Default Python version - Make sure to choose a version that suits your application
virtualenv --no-download $SLURM_TMPDIR/env
source $SLURM_TMPDIR/env/bin/activate
pip install mxnet --no-index
echo "starting training..."
python mxnet-example.py
```python title="mxnet-example.py" import numpy as np import time
from mxnet import context from mxnet import autograd, gpu, cpu from mxnet.gluon import nn, Trainer from mxnet.gluon.loss import SoftmaxCrossEntropyLoss from mxnet.gluon.data.vision import transforms from mxnet.gluon.data.vision.datasets import CIFAR10 from mxnet.gluon.data import DataLoader
import argparse
parser = argparse.ArgumentParser(description='cifar10 classification models, cpu performance test') parser.add_argument('--lr', default=0.1, help='') parser.add_argument('--batch_size', type=int, default=512, help='') parser.add_argument('--num_workers', type=int, default=0, help='')
def main():
args = parser.parse_args()
ctx = gpu() if context.num_gpus() > 0 else cpu()
net = nn.Sequential()
net.add(nn.Conv2D(channels=6, kernel_size=5, activation='relu'),
nn.MaxPool2D(pool_size=2, strides=2),
nn.Conv2D(channels=16, kernel_size=5, activation='relu'),
nn.MaxPool2D(pool_size=2, strides=2),
nn.Flatten(),
nn.Dense(120, activation="relu"),
nn.Dense(84, activation="relu"),
nn.Dense(10))
net.initialize(ctx=ctx)
criterion = SoftmaxCrossEntropyLoss()
trainer = Trainer(net.collect_params(),'sgd', {'learning_rate': args.lr})
transform_train = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
dataset_train = CIFAR10(root='./data', train=True).transform_first(transform_train)
train_loader = DataLoader(dataset_train, batch_size=args.batch_size, shuffle=True, num_workers=args.num_workers)
perf = []
for inputs, targets in train_loader:
inputs = inputs.as_in_context(ctx)
targets = targets.as_in_context(ctx)
start = time.time()
with autograd.record():
outputs = net(inputs)
loss = criterion(outputs, targets)
loss.backward()
trainer.step(batch_size=args.batch_size)
batch_time = time.time() - start
images_per_sec = args.batch_size/batch_time
perf.append(images_per_sec)
print(f"Current Loss: {loss.mean().asscalar()}")
print(f"Images processed per second: {np.mean(perf)}")
if name=='main': main()