Muy buenas, soy Miguel y esta vez les traigo un tutorial.
⚠️ Tenga en cuenta que esto fue escrito para la versión 1.0 y superior de AllenNLP y puede no ser relevante para versiones anteriores.
En este tutorial, le mostraremos cómo tomar un archivo de configuración de AllenNLP existente y modificarlo para que el allennlp train
El comando puede utilizar múltiples GPU en su máquina.
Bajo el capó, AllenNLP usa Marco de entrenamiento distribuido de PyTorch, torch.distributed
, por lo que a menudo usamos los términos “entrenamiento distribuido” y “entrenamiento multi-GPU” indistintamente (aunque técnicamente, el entrenamiento distribuido podría realizarse completamente en la CPU).
Utilizando torch.distributed
tiene varias ventajas sobre la alternativa para el entrenamiento multi-GPU, la DataParallel
envoltura de la antorcha.
… a pesar de que
DataParallel
es muy fácil de usar, normalmente no ofrece el mejor rendimiento. Esto se debe a que la implementación deDataParallel
replica el modelo en cada paso hacia adelante, y su paralelismo multiproceso de un solo proceso sufre naturalmente las contiendas de GIL.– https://pytorch.org/tutorials/beginner/dist_overview.html#torch-nn-dataparallel
Diferente a DataParallel
, torch.distributed
ejecuta un proceso de Python separado para cada GPU, por lo que la contención de GIL no es un problema. El modelo tampoco necesita ser replicado en cada pase hacia adelante.
Como resultado, torch.distributed
suele ser mucho más rápido, especialmente cuando se entrena con una gran cantidad de GPU.
El otro beneficio de usar torch.distributed
es que podremos admitir el entrenamiento de múltiples nodos en el futuro, es decir, entrenar un solo modelo utilizando GPU distribuidas en múltiples servidores. Pero como aún no lo hemos implementado, este tutorial solo se enfocará en el entrenamiento de un solo nodo.
Índice
Ahora vamos a sumergirnos en ello 👇
Para un ejemplo concreto, usaremos la Configuración de entrenamiento de TransformerQA, que se ve con el siguiente código:
Si tuviera que ejecutar el allennlp train
en este archivo de configuración tal como está, solo utilizaría una única GPU (siempre que haya una disponible, de lo contrario, recurre a la CPU).
Para que AllenNLP utilice múltiples GPU, todo lo que tiene que hacer es agregar una sección «distribuida» a su configuración de esta manera:
"distributed": { "cuda_devices": [0, 1, 2, 3], }
En este ejemplo, la matriz «cuda_devices» le dice a AllenNLP que use las cuatro GPU con ID 0
, 1
, 2
y 3
.
El archivo de configuración completo ahora se ve así:
Tenga en cuenta que lo único que ha cambiado es la adición de la sección «distribuida» en la parte inferior.
Aunque nada ha cambiado en la configuración aparte de agregar la sección «distribuida», hay algunas advertencias a tener en cuenta.
Tamaño de lote efectivo
En primer lugar, es importante saber que el parámetro «batch_size» del cargador de datos ahora representa el tamaño del lote por GPU. Eso significa que el tamaño de lote efectivo es en realidad batch_size
multiplicado por el número de GPU, o 8 * 4 = 32
en este caso.
Entonces, con un tamaño de lote efectivo más grande, es posible que deba ajustar otros hiperparámetros en su configuración, como la tasa de aprendizaje.
Carga de datos
Otra cosa a tener en cuenta es cómo se cargarán y dividirán sus datos en diferentes GPU.
De forma predeterminada, cada trabajador de GPU solo usará una fracción del total de instancias de cada archivo de datos. En este caso, dado que hay 4 GPU, cada trabajador obtendrá 1/4 del número total de instancias.
Sin embargo, su lector de conjuntos de datos debe estar «consciente» de la capacitación distribuida para que esto se haga de manera eficiente.
El uso de un lector de conjuntos de datos ingenuo significa que cada trabajador todavía tiene que leer y crear cada instancia de cada archivo de datos. Las instancias que el trabajador no necesita se filtran posteriormente.
Esto, por supuesto, no es muy eficaz. Idealmente, el lector de conjuntos de datos de cada trabajador solo debería tener que leer y crear el subconjunto de instancias que el trabajador necesita.
Pero para que eso suceda, el lector del conjunto de datos debe tener alguna lógica de «conocimiento distribuido» en su _read()
método.
Si bien generalmente no es demasiado difícil modificar cualquier lector de conjuntos de datos para manejar esta lógica, está más allá del alcance de este tutorial.
Para obtener información sobre la implementación de un lector «distribuido», consulte la DatasetReader
Documentación API.
Una forma alternativa de mejorar la eficiencia de la carga de datos desde el primer momento es utilizar un ShardedDatasetReader
.
Sin embargo, esto requiere que divida manualmente cada archivo de datos en varios archivos de datos más pequeños, o «fragmentos», cada uno de los cuales debe contener aproximadamente el mismo número de instancias. La cantidad de fragmentos debe ser igual (o múltiplo) de la cantidad de GPU que está utilizando.
Pero una vez que tenga sus fragmentos, cambie a usar el ShardedDatasetReader
es bastante simple. Todo lo que tiene que hacer es cambiar las rutas de datos en su configuración para que apunten al directorio o archivo de almacenamiento donde están sus fragmentos, y luego hacer una pequeña modificación en la sección «dataset_reader».
En nuestro ejemplo de TransformerQA, cambiaríamos nuestra sección «dataset_reader» para que se vea así:
"dataset_reader": { "type": "sharded", "base_reader": { // this is all the same as our old "dataset_reader" section. "type": "transformer_squad", "transformer_model_name": transformer_model, "skip_invalid_examples": true, } }
Métrica
Finalmente, tenga en cuenta que hay algunas métricas que actualmente no funcionan con el entrenamiento de múltiples GPU debido a la complejidad de sincronizar los cálculos entre trabajadores.
Pero tenemos un Tema abierto que está rastreando estas métricas, y está en nuestra lista para corregir antes de la versión 1.2.
A pesar de las advertencias, si tienes la suerte de tener varias GPU, ¡deberías usarlas! 😉
¡Eso es! ¡Feliz PNL-ing!
Espero que este tutorial haya sido útil. Si encuentra algún problema, deje un comentario.
Añadir comentario