Distributed Deep Learning con Horovod
Deep Learning ya era rápido y eficiente para procesar una gran cantidad de datos y redes complejas, sin embargo, parece que cuanto más grande es la solución, más puertas se abren para explorar sus límites. En este artículo, les presentaré qué es el Aprendizaje Profundo Distribuido, las principales estrategias que se están desarrollando para ello y explicaré paso a paso cómo usar Horovod, el marco más popular, creado por Uber y amado por varias empresas. ¡Una herramienta fácil de usar que puede permitirle ejecutar sus entrenamientos aún más rápido!
Distributed Deep Learning
El uso de múltiples GPU para ejecutar sus programas es esencial para resolver problemas de Deep Learning que manejan una gran cantidad de datos o redes neuronales artificiales con muchas capas. Además, con más facilidad para acceder a diversos recursos informáticos en los últimos años, con servicios en la nube como AWS, Google Cloud y Microsoft Azure. Los profesionales de Deep Learning e Inteligencia Artificial pueden acelerar aún más el entrenamiento de sus redes.
La estrategia para usar múltiples GPU a tu favor se llama Cómputo Distribuido y Paralelo (CPD), y básicamente consiste en dividir tu problema en subproblemas independientes y procesarlos al mismo tiempo, en paralelo. Las principales estrategias de CPD en Deep Learning son:
Paralelismo de datos: consiste en dividir el conjunto de datos y repartir un trozo a cada GPU. Cada GPU debe tener una copia del modelo de red y, al final de cada época, todos los gradientes obtenidos de cada GPU se calculan juntos para actualizar los pesos de su red. Recomendado para entrenamientos con muchos datos que se pueden extrapolar a la memoria de GPUs.
Paralelismo de modelos: consiste en dividir el modelo de red neuronal entre las GPU, de modo que cada dispositivo procesará en paralelo algunas de las capas de su red. Este es un enfoque más complejo, ya que requiere más sincronización y equilibrio de carga dividida para que ninguna GPU funcione mucho más que la otra. Recomendado para entrenamientos con redes muy profundas.
Paralelismo de capas: el más complejo de todos, que pretende insertar cómputo en los intervalos entre operaciones, cuando hay comunicación entre procesos y no se está utilizando la propia GPU. Por ejemplo, mientras una GPU intercambia datos con otras, otra GPU procesa la fase de propagación directa. Recomendado para lograr un rendimiento aún mejor sobre otras técnicas.
Híbrido: Una combinación de una o más de las técnicas anteriores.
Horovod
Horovod es una biblioteca de código abierto escrita en C++ y Python desarrollada por Uber en 2017 y ahora forma parte de la Fundación Linux. Además del propio Uber, la herramienta es utilizada por Amazon, IBM, NVIDIA, Alibaba y todas aquellas grandes empresas que necesitan procesar entrenamientos de redes neuronales artificiales a gran escala.
Horovod fue creado para hacer la vida más fácil a los profesionales en Deep Learning, buscando ofrecer un framework “low-code”, es decir, con poco código, pero que te permitirá avanzar mucho en tu trabajo en el área. Actuará como una "capa de rendimiento" sobre su modelo habitual implementado con TensorFlow, Keras, PyTorch o Apache MXNET. Horovod funciona tanto con GPU como con CPU.
Algoritmos
Horovod utiliza el paralelismo de datos mediante la implementación del algoritmo de comunicación en anillo ring-all-allreduce. Consiste en ejecutar varias copias de su secuencia de comandos de entrenamiento de red en diferentes GPU, donde cada GPU leerá una parte del conjunto de datos de entrenamiento, ejecutará su modelo de red en estos datos y calculará los gradientes, que se utilizarán para optimizar su red. Los gradientes calculados en la red se procesan en diferentes GPU y, al final, se comparten entre las GPU para que pueda tener gradientes finales relacionados con todos los datos.
*Una curiosidad es que el nombre “Horovod” proviene de un baile ruso con el mismo nombre donde los bailarines forman un círculo, lo que se asemeja al algoritmo de anillo utilizado.
Instalación (Linux)
Puedes instalarlo como un paquete de Python usando pip para un marco de aprendizaje profundo específico o para todos. Aprende más aquí. Ejemplo con TensorFlow:
$ HOROVOD_WITH_TENSORFLOW=1 pip install horovod[tensorflow]
O puedes instalar por línea de comando a través del repositorio oficial disponible aquí.
Verifica que se instaló correctamente usando:
$ pip list | grep horovod
Instala alguna distribución MPI (Message Passing Interface). Es la cual permitirá que Horovod intercambie información entre GPU en la red, incluso entre GPU en diferentes nodos computacionales. Deberás tener instalado un compilador GCC.
Comprueba si tienes GCC:
$ gcc –version
Si el comando no devuelve nada, deberás instalarse con el comando simple:
$ sudo apt install build-essential
Instala OpenMPI (lleva algo de tiempo):
$ wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.4.tar.gz
$ tar -xvf openmpi-4.1.4.tar.gz
$ cd openmpi-4.1.4/
$ ./configure –prefix=/usr/local
$ sudo make all install
Verifica que se instaló correctamente con:
$ mpirun –version
Primeros pasos (con TensorFlow)
Instala TensorFlow:
$ pip install tensorflow
La mayor ventaja de usar Horovod para distribuir su entrenamiento de red a múltiples GPU es la facilidad con la que la herramienta le permite hacerlo. Con unas pocas líneas de código, Horovod hará todo por usted "bajo el capó". ¿Vamos allá?
Cambia tu código de Python para agregar las operaciones de Horovod:
# Importa la biblioteca
import horovod.tensorflow.keras as hvd
# Inicia Horovod
hvd.init()
# Verifica que hay GPUs disponibles y distribuye un proceso por GPU
gpus = tf.config.experimental.list_physical_devices(’GPU’)
if gpus:
tf.config.experimental.set_visible_devices(gpus[hvd.local_rank()], ’GPU’)
# Verifica que todas las GPUs fueron encontradas
print("Eu sou a GPU: ", hvd.rank())
…
# Define el modelo de tu red aquí usando Keras!
…
model = keras.models.Model.from_config(model_config)
# Estoy usando el optimizador SGD, pero puedes usar el que quieras. Un consejo aquí es escalar la tasa de aprendizaje de la red (learning_rate) de acuerdo con el número de GPUs utilizadas (hvd.size())
opt = keras.optimizers.SGD(learning_rate=args.learning_rate * hvd.size())
# Agregue el optimizador de distribución de aprendizaje profundo de Horovod, que "envolverá" el optimizador de Keras para aplicar el paralelismo de datos.
opt = hvd.DistributedOptimizer(opt)
# Compila tu modelo de red utilizando el optimizador de Horovod
model.compile(optimizer = opt, … )
# Envía los estados iniciales de las variables de tu programa para que todos los procesos tengan acceso
callbacks = [hvd.callbacks.BroadcastGlobalVariablesCallback(0),]
...
# ¡Implementa el entrenamiento de tu red normalmente!
# Una sugerencia es dividir la cantidad de iteraciones de su entrada por la cantidad de GPU utilizadas, para asegurarte de que tu entrada se adapte bien a más dispositivos. Hice esto para el paso de entrenamiento y validación.
model.fit(train_iter,
steps_per_epoch=len(train_iter) // hvd.size(),
callbacks=callbacks,
epochs=args.epochs,
verbose=verbose,
workers=args.my_workers,
use_multiprocessing = False,
validation_data=test_iter,
validation_steps = 3 * len(test_iter) // hvd.size())
Ahora solo ejecuta el entrenamiento de tu red:
$ horovodrun -np 2 python script.py
El parámetro np definirá la cantidad de procesos paralelos que ejecutará Horovod, es decir, la cantidad de GPU que tienes en tu sistema. También puedes ejecutarlo directamente con el comando OpenMPI:
$ mpirun -np 2 python script.py
Ejecutar con uno u otro no hará una diferencia en el rendimiento de tu aplicación. Para obtener la lista de todos los parámetros disponibles, puedes utilizar:
$ horovodrun –help
Horovod timeline
Esta es la herramienta nativa de Horovod para analizar el perfil de ejecución de tu aplicación. Después de todo, si usamos computación distribuida, queremos saber si realmente estamos aprovechando todos los procesadores utilizados.
Para usarlo, simplemente ejecútalo con el parámetro para recopilar el perfil de ejecución:
$ horovodrun -np 2 — timeline-filename nome_do_arquivo_de_saida.json python script.py
Este comando asegurará que al final de la ejecución tengas un archivo en formato JSON que podrás visualizar en Google Chrome, utilizando el Tracing Viewer, accediendo a “chrome://tracing viewer” e importando tu archivo local.
Muestra la línea de tiempo de la ejecución de su red y las operaciones que se llamaron, todo en una vista interactiva donde puede arrastrar, hacer zoom y seleccionar partes de la ejecución. Al seleccionarlo, se abrirá un panel con el resumen del desempeño en ese intervalo de ejecución, como el número de llamadas y el tiempo de ejecución de cada operación. Con esta vista, puede, por ejemplo, asegurarse de que su entrenamiento esté utilizando todas las GPU correctamente.
Conclusión
En un futuro con más y más poder computacional para ser utilizado, Horovod es sin duda una herramienta que llegó para quedarse. Si trabajas con aprendizaje profundo y/o está interesado/a en la computación de alto rendimiento, te sugiero invertir unas horas para aprender más sobre esta herramienta y utilizarla en tu beneficio. Mi consejo es que comiences a distribuir una red simple como MNIST, fashion MNIST y ResNet-50.
¿Te gustó el contenido? Si tienes alguna pregunta, déjala aquí en los comentarios y con gusto te ayudaré.
Referencias
Documentación: https://horovod.readthedocs.io/
Artículo oficial: https://arxiv.org/abs/1802.05799
Aviso de lanzamiento en el sitio web de Uber: https://eng.uber.com/horovod/
Ejemplos de uso de Horovod para diferentes marcos: https://github.com/horovod/horovod/tree/3f08a1a872a46f62639a9d660e66ce41e042f206/examples
Revelo Content Network da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.