HorovodRunner: aprendizaje profundo distribuido con Horovod
Importante
Horovod y HorovodRunner ya están en desuso. Las versiones posteriores a 15.4 LTS ML no tendrán este paquete preinstalado. Para el aprendizaje profundo distribuido, Databricks recomienda usar TorchDistributor para el entrenamiento distribuido con PyTorch o la API para el tf.distribute.Strategy
entrenamiento distribuido con TensorFlow.
Aprenda a realizar el entrenamiento distribuido de modelos de aprendizaje automático mediante HorovodRunner para iniciar trabajos de entrenamiento Horovod como trabajos de Spark en Azure Databricks.
¿Qué es HorovodRunner?
HorovodRunner es una API general para ejecutar cargas de trabajo distribuidas de aprendizaje profundo en Azure Databricks mediante el marco Horovod. Al integrar Horovod con el modo de barrera de Spark, Azure Databricks puede proporcionar una mayor estabilidad en los trabajos entrenamiento para el aprendizaje profundo de larga duración de Spark. HorovodRunner usa un método de Python que contiene código de entrenamiento de aprendizaje profundo con enlaces de Horovod. HorovodRunner selecciona el método en el controlador y lo distribuye a los trabajos de Spark. Un trabajo de MPI de Horovod se inserta como un trabajo de Spark mediante el modo de ejecución de barrera. El primer ejecutor recopila las direcciones IP de todos los ejecutores de tareas mediante BarrierTaskContext
y desencadena un trabajo de Horovod mediante mpirun
. Cada proceso MPI de Python carga el programa de usuario en pickled, lo deserializa y lo ejecuta.
Aprendizaje distribuido mediante HorovodRunner
HorovodRunner le permite iniciar trabajos de entrenamiento de Horovod como trabajos de Spark. La API HorovodRunner admite los métodos que se muestran en la tabla. Para obtener más información, consulte la documentación de la API HorovodRunner.
Método y firma | Descripción |
---|---|
init(self, np) |
Cree una instancia de HorovodRunner. |
run(self, main, **kwargs) |
Ejecute un trabajo de entrenamiento de Horovod invocando main(**kwargs) . La función principal y los argumentos de palabras clave se serializan mediante cloudpickle y se distribuyen a los trabajadores del clúster. |
El enfoque general para desarrollar un programa de entrenamiento distribuido mediante HorovodRunner es:
- Cree una instancia
HorovodRunner
inicializada con el número de nodos. - Defina un método de entrenamiento de Horovod de acuerdo con los métodos descritos en Uso de Horovod y asegúrese de agregar cualquier instrucción de importación en el método.
- Pase el método de entrenamiento a la instancia
HorovodRunner
.
Por ejemplo:
hr = HorovodRunner(np=2)
def train():
import tensorflow as tf
hvd.init()
hr.run(train)
Para ejecutar HorovodRunner en el controlador solo con subprocesos n
, use hr = HorovodRunner(np=-n)
. Por ejemplo, si hay 4 GPU en el nodo del controlador, puede elegir entre n
y 4
como máximo. Para obtener más información sobre el parámetro np
, consulte la documentación de la API HorovodRunner. Para obtener más información sobre cómo anclar una GPU por subproceso, consulte la guía de uso de Horovod.
Un error común es que los objetos TensorFlow no se pueden encontrar ni seleccionar. Esto sucede cuando las instrucciones de importación de la biblioteca no se distribuyen a otros ejecutores. Para evitar este problema, incluya todas las instrucciones de importación (por ejemplo, import tensorflow as tf
) en la parte superior del método de entrenamiento de Horovod y dentro de cualquier otra función definida por el usuario que se haya llamado en el método de entrenamiento de Horovod.
Registro del entrenamiento de Horovod con Horovod Timeline
Horovod tiene la capacidad de registrar la escala de tiempo de su actividad, denominada Escala de tiempo de Horovod.
Importante
La escala de tiempo de Horovod tiene un impacto significativo en el rendimiento. El rendimiento de Inception3 puede disminuir en más o menos un 40 % cuando la escala de tiempo de Horovod está habilitada. Para acelerar los trabajos de HorovodRunner, no use la escala de tiempo de Horovod.
Recuerde que no puede ver la escala de tiempo de Horovod mientras el entrenamiento está en curso.
Para registrar una escala de tiempo de Horovod, establezca la variable de entorno HOROVOD_TIMELINE
en la ubicación donde quiera guardar el archivo de escala de tiempo. Databricks recomienda usar una ubicación en el almacenamiento compartido para que el archivo de escala de tiempo se pueda recuperar fácilmente. Por ejemplo, puede usar las API de archivo local de DBFS, tal como se muestra:
timeline_dir = "/dbfs/ml/horovod-timeline/%s" % uuid.uuid4()
os.makedirs(timeline_dir)
os.environ['HOROVOD_TIMELINE'] = timeline_dir + "/horovod_timeline.json"
hr = HorovodRunner(np=4)
hr.run(run_training_horovod, params=params)
A continuación, agregue código específico de la escala de tiempo al principio y al final de la función de entrenamiento. El siguiente cuaderno de ejemplo incluye código de ejemplo que puede utilizar como solución para ver el progreso del entrenamiento.
Cuaderno de ejemplo de la escala de tiempo de Horovod
Para descargar el archivo de escala de tiempo, use la CLI de Databricks y, a continuación, use la instalación del explorador Chrome chrome://tracing
para verla. Por ejemplo:
Flujo de trabajo de desarrollo
Estos son los pasos generales que debe dar para migrar código de aprendizaje profundo de nodo único al entrenamiento distribuido. Los Ejemplos: Migrar al aprendizaje profundo distribuido con HorovodRunner de esta sección ilustran estos pasos.
- Preparación del código de nodo único: Prepare y pruebe el código de nodo único con TensorFlow, Keras o PyTorch.
- Migración a Horovod: Siga las instrucciones de la guía de uso de Horovod para migrar el código con Horovod y probarlo en el controlador:
- Agregue
hvd.init()
para inicializar Horovod. - Ancle una GPU de servidor para que la use este proceso mediante
config.gpu_options.visible_device_list
. Con la configuración típica de una GPU por proceso, esta opción se puede establecer en un rango local. En ese caso, al primer proceso del servidor se le asignará la primera GPU, al segundo proceso se le asignará la segunda GPU, y así sucesivamente. - Incluya una partición del conjunto de datos. Este operador de conjunto de datos es muy útil al ejecutar el entrenamiento distribuido, ya que permite a cada trabajo leer un subconjunto único.
- Escale la tasa de aprendizaje por número de trabajos. El tamaño efectivo del lote en el entrenamiento distribuido sincrónico se escala según el número de trabajos. Así pues, aumentar la velocidad de aprendizaje compensa el aumento del tamaño del lote.
- Ajuste el optimizador en
hvd.DistributedOptimizer
. El optimizador distribuido delega el cálculo de degradado en el optimizador original, realiza el promedio de los degradados mediante allreduce o allgather y, a continuación, aplica los degradados según el promedio. - Agregue
hvd.BroadcastGlobalVariablesHook(0)
a los estados iniciales de la variable de difusión a partir del rango 0 a todos los demás procesos. Esto es necesario para garantizar una inicialización coherente de todos los trabajos cuando el entrenamiento se inicia con pesos aleatorios o si se restaura desde un punto de control. Como alternativa, si no usaMonitoredTrainingSession
, puede ejecutar la operaciónhvd.broadcast_global_variables
una vez inicializadas las variables globales. - Modifique el código para guardar los puntos de control solo en el trabajo 0 para evitar que otros trabajos provoquen errores.
- Agregue
- Migración a HorovodRunner: HorovodRunner ejecuta el trabajo de entrenamiento de Horovod invocando una función de Python. Asegúrese de encapsular el procedimiento de entrenamiento principal en una sola función de Python. A continuación, puede probar HorovodRunner en modo local y en modo distribuido.
Actualización de las bibliotecas de aprendizaje profundo
Si actualiza TensorFlow, Keras o PyTorch (o cambia a una versión anterior de estos), debe volver a instalar Horovod para que se compile en la biblioteca recién instalada. Por ejemplo, si quiere actualizar TensorFlow, Databricks es recomendable que use el script init de las instrucciones de instalación de TensorFlow y anexe al final el siguiente código de instalación específico de TensorFlow para Horovod. Consulte las instrucciones de instalación de Horovod para trabajar con diferentes combinaciones, como actualizar PyTorch y otras bibliotecas (o cambiar a una versión anterior).
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt update
# Using the same compiler that TensorFlow was built to compile Horovod
apt install g++-7 -y
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60
HOROVOD_GPU_ALLREDUCE=NCCL HOROVOD_CUDA_HOME=/usr/local/cuda pip install horovod==0.18.1 --force-reinstall --no-deps --no-cache-dir
Ejemplos: Migrar al aprendizaje profundo distribuido con HorovodRunner
En los ejemplos siguientes, que están basados en el conjunto de datos MNIST, se muestra cómo migrar un programa de aprendizaje profundo de un solo nodo al aprendizaje profundo distribuido con HorovodRunner.
- Entrenamiento de aprendizaje profundo distribuido mediante TensorFlow con HorovodRunner para MNIST
- Adaptar PyTorch de nodo único para el aprendizaje profundo distribuido
Limitaciones
- Al trabajar con archivos de área de trabajo, HorovodRunner no funcionará si
np
está establecido en mayor que 1 y el cuaderno importa desde otros archivos relativos. Considere la posibilidad de usar horovod.spark en lugar deHorovodRunner
. - Si se producen errores como
WARNING: Open MPI accepted a TCP connection from what appears to be a another Open MPI process but cannot find a corresponding process entry for that peer
, esto indica un problema con la comunicación de red entre los nodos del clúster. Para resolver este error, agregue el siguiente fragmento de código en el código de entrenamiento para usar la interfaz de red principal.
import os
os.environ["OMPI_MCA_btl_tcp_if_include"]="eth0"
os.environ["NCCL_SOCKET_IFNAME"]="eth0"