noticias

Desde bare metal hasta un modelo grande con 70 mil millones de parámetros, aquí hay un tutorial y scripts listos para usar.

2024-07-24

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina



Seleccionado de imbue.com

Autor: Equipo Imbuir

Compilación del corazón de la máquina

Editor: panda

Sabemos que LLM se capacita en grupos de computadoras a gran escala utilizando datos masivos. Machine Heart ha introducido muchos métodos y tecnologías para ayudar y mejorar el proceso de capacitación de LLM. Hoy, lo que queremos compartir es un artículo que profundiza en la tecnología subyacente y presenta cómo convertir un grupo de "metales desnudos" que ni siquiera tienen un sistema operativo en un grupo de computadoras para capacitar LLM.

Este artículo proviene de Imbue, una startup de inteligencia artificial que se esfuerza por lograr inteligencia general al comprender cómo piensan las máquinas.

Por supuesto, convertir un montón de "metal básico" sin un sistema operativo en un grupo de computadoras para capacitar a un LLM no es un proceso fácil, lleno de exploración y prueba y error, pero Imbue finalmente entrenó con éxito un LLM con 70 mil millones de parámetros y acumulados. muchas experiencias útiles en el proceso.

Este artículo proporcionará una introducción detallada a todo el proceso del equipo para construir su propia infraestructura de capacitación LLM y compartirá las muchas herramientas y scripts que escribieron para facilitar el monitoreo, la inspección y la corrección de errores.

Si está interesado en construir su propia infraestructura de capacitación de LLM o tiene curiosidad acerca de cómo se hace el LLM, entonces vale la pena leer y recopilar este artículo.

El siguiente es el texto original del artículo del equipo Imbue.

introducción

Nuestro pequeño equipo de investigadores e ingenieros pasó varios meses entrenando un modelo de 70 mil millones de parámetros desde cero en nuestra propia infraestructura, y el modelo superó a los modelos de disparo cero en tareas relacionadas con la inferencia.

Hoy, compartimos el proceso de configuración de la infraestructura requerida: desde armar el clúster inicial e instalar el sistema operativo hasta configurar la recuperación automática cuando se encuentran errores durante el entrenamiento. Detallamos los desafíos encontrados y las soluciones en cada paso. Además de estos aprendizajes, también publicaremos muchos de los scripts que hemos desarrollado a lo largo del camino para facilitar a otros equipos la creación de una infraestructura estable para su propio entrenamiento modelo.

A lo largo del proceso, nuestro equipo de ingenieros trabajó con Voltage Park para preparar grupos de computadoras y sentar las bases para las aplicaciones de producción. Todo este proceso incluye:

1. Configurar cada máquina

2. Configurar InfiniBand

3. Asegúrate de que la máquina esté completamente sana.

4. Diagnosticar problemas comunes de entrenamiento

5. Mejorar las herramientas de infraestructura

Cada paso se describe en detalle a continuación.

Antecedentes: cómo se hizo

Nuestro objetivo al realizar cálculos es garantizar una experimentación rápida con modelos de lenguaje grandes. Para hacer esto, necesitamos una gran cantidad de GPU de alta velocidad y una comunicación de alta velocidad entre estas GPU.

Este artículo se centrará en un clúster que contiene 4088 GPU H100 distribuidas en 511 computadoras u 8 GPU por computadora. La razón por la que hay 511 computadoras con GPU es porque algunas conexiones deben reservarse para el nodo Unified Fabric Manager, cuya función es administrar la red InfiniBand. En los hosts equipados con 511 GPU, cada GPU está conectada directamente a una tarjeta de red ConnectX-7, que puede transmitir datos a 400 Gbps a cualquier GPU en la red InfiniBand.

Nuestra topología de red InfiniBand es "completamente sin bloqueo" en teoría, lo que permite que las GPU se comuniquen entre sí a la máxima velocidad. Para ello, utilizamos una arquitectura de red InfiniBand de tres capas: conmutadores InfiniBand de tres capas. Con las conexiones adecuadas, este alto nivel de rendimiento se puede lograr en toda la red. La siguiente figura muestra una descripción general de esta red InfiniBand:



Tenga en cuenta que la comunicación durante el entrenamiento de la red se produce a través de InfiniBand, no de Ethernet. Aunque estas máquinas también están conectadas a Ethernet, la función de esta red es transportar datos como conjuntos de datos y puntos de control. Si usa Ethernet para enviar datos, la velocidad será mucho más lenta porque los datos primero viajarán desde la GPU a la CPU y luego saldrán a través de la tarjeta Ethernet de velocidad de 100 Gbps. Aunque también es posible entrenar a través de Ethernet utilizando una tecnología llamada RDMA sobre Ethernet convergente (RoCE), que requiere mucho trabajo adicional tanto en el lado del hardware como del software y, en general, es menos confiable que InfiniBand. Para obtener más información, consulte este documento: https://arxiv.org/pdf/2402.15627

También hay una Ethernet secundaria que se usa solo para configuración y administración, brindando acceso al BIOS (Sistema básico de entrada y salida), fuente de alimentación y otras interfaces de control para interfaces de máquina de bajo nivel. Sin esta red de administración, tendríamos que configurar manualmente cada nodo mediante un controlador USB, un teclado y un monitor. Para situaciones con cientos de máquinas, este no es un enfoque sostenible.

Lograr una capacitación de alto rendimiento en este clúster requiere que todos los componentes (InfiniBand, Ethernet, GPU y los propios nodos) funcionen casi a la perfección. Si alguna de esas más de 12.000 conexiones es un poco inestable, puede ralentizar el proceso de entrenamiento general.

El resto de este artículo trata sobre cómo hacer que todo funcione de manera perfecta y estable.

Proceso: cómo convertir el hardware básico en un clúster totalmente operativo

Configurar cada máquina

Después de establecer la conexión Ethernet inicial al clúster a través de la red de administración, se obtienen las credenciales de acceso al controlador de administración de la placa base (BMC). Un BMC es un procesador de servicios dedicado que monitorea de forma remota los sistemas host y generalmente está conectado a una red separada. Nos permite operar la máquina como si estuviéramos allí en persona y, además, proporciona API para el estado del hardware, la configuración del BIOS y la administración de energía.

Con estos componentes en su lugar, podemos arremangarnos y comenzar a configurar el clúster.

Paso 0: primero configure una máquina

Comenzamos instalando Ubuntu 22.04 en un servidor usando iDRAC (Controlador de administración de placa base de Dell) y luego configuramos todo lo demás en función de este sistema operativo. Una de las capacidades de iDRAC es permitir la instalación y el inicio de imágenes ISO desde la computadora local y proporcionar una consola virtual a través del navegador. Idealmente, este es el único paso de instalación manual del proceso.

Paso 1: Instale el sistema operativo en cada máquina

Después de configurar la primera máquina, proceda a instalar el software Metal-as-a-Service (MAAS) de Ubuntu para ayudar a configurar los servidores restantes. La herramienta de automatización y arranque de iDRAC utiliza el protocolo de entorno de ejecución previo al arranque (PXE) para indicar a cada máquina que arranque desde la red y configurar MAAS para responder a las solicitudes de arranque PXE. Al realizar un arranque de red inicial, el servidor obtiene una IP y un kernel inicial de MAAS a través del protocolo de asignación dinámica de IP DHCP sin tener que instalar nada en la unidad local. Este es el entorno básico para automatizar instalaciones repetibles de sistemas operativos. En teoría, sólo tenemos que esperar al primer arranque y todo estará solucionado. Pero en la práctica, la integración de MAAS con BMC no es confiable, por lo que utilizamos la API de iDRAC para recopilar la dirección MAC de cada máquina (un identificador de hardware físico único) de antemano.

A lo largo de todo este proceso de entrenamiento, el MAAS suele ser el componente más fiable del conjunto vertebral. Sin embargo, al principio encontramos algunos problemas que eran exclusivos de nuestra configuración. Por ejemplo, al configurar las primeras máquinas, no pude instalar nada a través de apt debido a problemas de verificación del certificado HTTPS porque los relojes eran muy diferentes. De manera relacionada, dado que el servidor MAAS tiene que ser responsable de muchas cosas (servidor DHCP, servidor DNS para resolver nombres de host en IP, proxy HTTP entre el host y el servidor de paquetes oficial de Ubuntu, servidor NTP, administración de configuración de inicio en la nube, un terreno La base de datos de verdad se utiliza para conectar la dirección MAC, la IP, el nombre de host y los metadatos personalizados), por lo que nos resulta difícil resolver estos problemas desde la raíz. Además, está la cuestión de la curva de aprendizaje del ciclo de vida de la configuración de MAAS, ya que el objetivo del diseño es manejar la complejidad de gestionar implementaciones nuevas y la migración gradual de nodos y varios estados intermedios de depuración/no saludables.

Paso 2: diagnosticar la máquina rota

Descubrimos que alrededor del 10% de las máquinas no arrancaban, principalmente debido a problemas físicos con el servidor. Este es un escenario común para configurar grandes clústeres de GPU. Las situaciones que encontramos incluyen: cables de red faltantes o incorrectos, problemas de hardware en iDRAC, unidades de fuente de alimentación dañadas, controladores NVME (memoria rápida no volátil) dañados, líneas internas faltantes, tarjetas de red o GPU que no se muestran. Verificamos automáticamente estos problemas, devolvimos algunas máquinas a Dell para que las volvieran a probar y enviamos las órdenes de trabajo apropiadas para el personal del centro de datos. Una ventaja de configurar el clúster nosotros mismos es que podemos usar inmediatamente máquinas en buen estado mientras esperamos el mantenimiento en algunas máquinas.

Paso 3: Máquina observable mínima viable

Seguimos con las siguientes configuraciones en cada servidor:

1.Docker (para facilitar la ejecución de servicios y trabajos de capacitación)

2. Controlador de GPU del centro de datos

3. Herramienta de exportación de nodos Prometheus (utilizada para exportar flujo de datos de indicadores de hardware/sistema operativo estables)

4.Herramienta de exportación DCGM (utilizada para exportar datos de indicadores adicionales de la GPU NVIDIA, como el estado de la GPU, el reloj y la utilización)

5. Grupo RAIDZ ZFS para todos los controladores que no son del sistema operativo, que permite que la máquina continúe funcionando incluso si falla un controlador, al tiempo que proporciona compresión transparente de forma gratuita (esto es especialmente útil para conjuntos de datos de texto sin formato y registros repetitivos; relativamente Uso de esto La herramienta normalmente aumenta el espacio utilizable hasta 10 veces en comparación con no usar esta herramienta)

Luego ejecutamos diagnósticos básicos de la GPU para determinar si la GPU funciona correctamente en general; cualquier cosa que no funcione normalmente generará problemas de hardware en unas pocas horas.

Durante este tiempo, encontramos cuellos de botella en el ancho de banda al intentar instalar paquetes en los 400 nodos simultáneamente. Esta es la primera vez que recibimos alertas de sobrecalentamiento de alta temperatura en múltiples componentes implementados en nuestro centro de datos. Estos primeros problemas de calefacción se han resuelto en gran medida mediante actualizaciones de firmware.

Paso 4: entrenamiento de GPU de un solo nodo

El siguiente paso es garantizar que cada máquina pueda manejar cargas de trabajo reales de GPU por sí sola. Muchas máquinas no pueden hacer esto y los problemas incluyen:

Errores relacionados con la GPU, que generalmente se pueden resolver reinsertando la tarjeta GPU en la ranura para tarjetas: deslice el servidor de 200 libras fuera del bastidor, retire todos los cables entre la cubierta y la GPU, retire la GPU, reinstale la GPU y luego Vuelva a conectar los cables y empuje el servidor nuevamente hacia el bastidor.

Según los registros del servidor Ubuntu, muchos cables entre la GPU y el bus PCIe o la tarjeta de red emitieron este error: "ancho limitado: x4 < x16". Después de actualizar el firmware del bus del conmutador PCIe, descubrimos que aproximadamente una cuarta parte de los hosts requirieron volver a colocar los cables PCIe internos, presumiblemente porque los cables entre la carcasa y la GPU son bastante frágiles, lo que significa que siempre que se realiza mantenimiento en la GPU, estos cables se dañarán. ser empujado o sacado.

Hubo algunas interrupciones diversas que también afectaron a varios hosts. Dell nos ayudó a resolver algunos problemas con una actualización de firmware:

La unidad NVMe no mostró fallas, pero bloqueó toda la máquina cuando se tocó.

Los discos duros aparecen en orden aleatorio en Linux, lo que genera confusión en MAAS y provoca que el sistema operativo se instale en el disco incorrecto.

La lectura de temperatura es incorrecta, lo que hace que el ventilador funcione a máxima velocidad todo el tiempo. El motivo puede ser un problema con el controlador NVIDIA, que se soluciona bajando la versión del controlador.

El escalado dinámico de la CPU se salió de control, limitando los núcleos de trabajo a 2 GHz.

La comunicación directa GPU-GPU (GDR o GPUDirect RDMA Peer Memory Client) no se puede aplicar correctamente.

Configurar InfiniBand

Paso 0: instale UFM

Una ventaja de InfiniBand es su diseño centralizado, de modo que toda la red tiene un solo cerebro. Por lo tanto, solo necesitamos tratar con una instancia de los 320 conmutadores de red en toda la estructura de la red. Nuestra primera tarea fue determinar qué interruptor conectaba qué máquinas, luego asociarlo con el diagrama de cableado y cambiarles el nombre según la ubicación física del interruptor.

Paso 1: volver a cablear

Inicialmente, UFM no pudo detectar esos 320 conmutadores, y mucho menos los hosts que se suponía estaban presentes en la estructura. Después de consultar con nuestros socios de centros de datos, confirmamos que los conmutadores estaban encendidos y cableados, pero aún no pudimos detectarlos. Después de examinar la lista de cableado de la red, notamos que el diseño de nivel superior de la estructura de la red era incorrecto: en lugar de estar unificada, la estructura estaba dividida en ocho redes desconectadas sin una ruta de enrutamiento común. Después de volver a cablear, agregamos un paso de verificación para verificar que todas las conexiones físicas sean consistentes con el nuevo diseño.

Paso 2: Diez mil alarmas de temperatura (alerta)

Una vez que se resolvieron los problemas de cableado físico, InfiniBand estableció con éxito conexiones a todos los conmutadores InfiniBand en la estructura de la red. Sin embargo, casi todos los puertos de switch comenzaron a reportar temperaturas excesivas, a veces superando los 70°C, a pesar de que no estaban transmitiendo datos. Descubrimos que el problema se debía al espacio abierto entre los interruptores en el mismo rack, lo que provocaba que el aire caliente regresara al frente. Nuestro socio del centro de datos nos ayudó a diagnosticar rápidamente el problema y desarrollar una solución adecuada.

Paso 3: 1800 alarmas

Muchos puertos también tienen altas tasas de error, o van y vienen entre estados normales y corruptos, lo que se llama "flapping". Estos problemas sólo surgen cuando los puertos realmente se utilizan, por lo que son difíciles de detectar con antelación porque toda nuestra estructura consta de 10.000 enlaces altamente redundantes. Nuestro socio del centro de datos ayudó a limpiar y reinstalar los puertos de la alarma, y ​​desactivamos los transceptores de alarma restantes mientras esperábamos el reemplazo.

Si bien InfiniBand es resistente a fallas de hardware, una vez que alrededor del 10% de la estructura comienza a fallar, funciones como el enrutamiento adaptativo no funcionan de manera confiable para compensar la pérdida ocasional de un enlace.

Durante este tiempo, ejecutamos con éxito una capacitación de múltiples nodos utilizando entre 100 y 200 máquinas. Nuestro proceso es algo improvisado: a veces activamos un conjunto aleatorio de nodos, observamos su rendimiento y luego intentamos mantener en funcionamiento tantos como sea posible. Este método nos permite encontrar un subconjunto confiable de la estructura de red InfiniBand, pero es muy difícil porque cada vez necesitamos cambiar el conjunto de nodos utilizados para el entrenamiento, cambiando así el enlace predeterminado de InfiniBand.

Paso 4: InfiniBand arde como loco

Para diagnosticar los problemas de InfiniBand de manera más eficiente, diseñamos una carga de trabajo para todo el clúster que envió la mayor cantidad de datos posible a través de cada puerto de la estructura simultáneamente. Esto es diferente de ejecutar una gran carga de trabajo reducida en todo el clúster, lo que requiere el uso de NCCL para optimizar la comunicación entre nodos individuales mediante el uso de NVLink para la comunicación de GPU a través de las ranuras del módulo PCIe del servidor (SXM).

En lugar de ello, optamos por un enfoque de fuerza bruta y lo logramos con facilidad. UFM comenzará a emitir alertas cuando el volumen de transferencia de datos en la mayoría de los puertos supere el 97% de la capacidad teórica y algunos conmutadores dejarán de funcionar temporalmente. Cada puerto que pensamos que llegó al final del día era lo suficientemente robusto, y el resto fue desactivado o eliminado en espera de reparación.

Paso 5: GPUDirect RDMA

Para permitir la comunicación de GPU sin incurrir en una sobrecarga informática de la CPU, habilitamos una función llamada GPUDirect RDMA, que permite la comunicación directa entre tarjetas de red InfiniBand. Esto implica dos pasos clave:

1. Inicie un módulo de kernel adicional

2. Asegúrese de que el Servicio de control de acceso (ACS) PCIe esté deshabilitado para evitar bloqueos inmediatos (cuelgues inmediatos)

Paso 6: expanda el servidor "oro"

Para construir un clúster de GPU utilizando el hardware más reciente, una regla general es estar preparado para que aproximadamente el 3% de sus máquinas fallen cada semana.

Sin embargo, cabe señalar: no todas las máquinas tienen una probabilidad uniforme del 3% de fallar, pero un pequeño número de máquinas no tratadas tienen varios problemas repetidamente hasta que se reparan adecuadamente. Esto resalta las ventajas de tener una gran cantidad de máquinas en una misma estructura de red. Entonces, en lugar de simplemente encontrar máquinas aleatorias para ejecutar entrenamiento a gran escala, como golpear a un topo para ver qué se rompe, nuestro enfoque es centrarnos en escalar servidores que se sabe que son confiables, los servidores "dorados".

Paso 7: Mantenimiento

El mantenimiento de InfiniBand implica principalmente responder a alarmas UFM, reemplazar cables y transceptores defectuosos y, ocasionalmente, diagnosticar errores más difíciles (como fallas de interruptores). Generalmente hay dos factores que conducen a un mantenimiento a gran escala:

1. Las actualizaciones de firmware, especialmente cuando solo la mitad del clúster ha completado la actualización, pueden provocar un estado de UFM dañado y requerir un reinicio de UFM en todos los conmutadores InfiniBand.

2. Las cajas de GPU se reinician masivamente al mismo tiempo, lo que puede inyectar una gran cantidad de actualizaciones en el estado UFM y también requerir reiniciar el servicio UFM.

Asegúrese de que la máquina esté completamente sana.

En el camino, descubrimos múltiples formas en las que las máquinas individuales podrían funcionar mal o ralentizar el entrenamiento. Muchos de estos modos de falla no son evidentes de inmediato, por lo que escribimos una serie de scripts de verificación de estado para verificar si el host estaba lo suficientemente saludable. Publicamos el código aquí: https://github.com/imbue-ai/cluster-health

Tenga en cuenta que muchas de estas comprobaciones de estado son específicas de nuestro entorno de ejecución y no están necesariamente relacionadas con el hardware subyacente, ni son necesariamente fáciles de reparar o automatizar. Esto fue así por diseño: para lograr el objetivo general de preparar nuestras máquinas para el entrenamiento, queríamos un punto de entrada único que pudiera responder a un simple sí o no, y que pudiera resumir cualquier cantidad de detalles finos.

Comprobación de estado de la GPU

Verificamos que la cantidad de GPU fuera correcta, que la verificación ECC (Código de corrección de errores) estuviera habilitada y que no hubiera errores ECC. También verificamos que la topología NVLink (que conecta las GPU entre sí) esté funcionando sin errores.

Comprobación del estado del espacio en disco

Verificamos si la utilización del espacio en disco del host supera el 95%.

Comprobación de estado de Docker

Verificamos que Docker puede ejecutar contenedores con la GPU conectada (es decir, NVIDIA Container Runtime funciona correctamente) y que los contenedores Docker relacionados con el monitoreo/análisis están activados y tienen los permisos de host correctos.

control de salud de dmesg

Verificamos dmesg en busca de errores de hardware Xids o SXid (fallos causados ​​por GPU NVIDIA o conmutadores NVIDIA entre GPU). También leemos todas las líneas de registro dmesg para verificar que todas puedan clasificarse en la lista Líneas de registro comunes/esperadas.

Comprobación de estado de iDRAC

Verificamos errores de iDRAC en la máquina, que ignoraron mensajes de error no fatales. Esta es una verificación específica para las computadoras Dell, por lo que no está incluida en nuestro código fuente abierto.

Comprobación del estado del disco

Verificamos que zpool esté instalado, que Docker esté conectado correctamente y que realmente pueda acceder a él sin bloquear la CPU.

Comprobación de estado de InfiniBand

Verificamos si la tasa de errores de InfiniBand aumentó y/o si el firmware del controlador no estaba actualizado.

Comprobación de estado de nvlink

Verificamos errores de NVLink en la máquina. En la práctica, esto no parece provocar fallos en el entrenamiento, pero puede ralentizarlo.

Control de salud de la RDA

Verificamos si GDR está habilitado en la máquina.

Comprobación de estado de VBIOS

Verificamos que la versión VBIOS de la GPU y el firmware de la placa base H100 estuvieran actualizados.

Control de salud de pedernal

Usamos flint y hca_self_test para verificar que el controlador Mellanox OFED, el firmware de la tarjeta de red y el firmware del transceptor tuvieran las versiones correctas y que estuvieran compilados correctamente para el controlador NVIDIA.

control de salud del PSB

Consultamos los dispositivos PCIe para verificar si la velocidad de conexión y el ancho entre la GPU, el PSB (PCIe Switch Bus) y la tarjeta de red eran los que esperábamos. También verificamos que el firmware del conmutador esté actualizado. Este script fue desarrollado por Dell, no por Imbue, por lo que no podemos compartirlo en este momento.

Además de estos controles de salud rápidos, también realizamos controles de salud más complejos, que incluyen:

Inicialice los cálculos matriciales a través de PyTorch y mida el ancho de banda de NVLink y la velocidad y la memoria de cálculo de la GPU. Configuramos los indicadores GDR apropiados para probar InfiniBand y NVLink.

Utilice ib_write_bw y –use_cuda para enviar datos a través de la tarjeta IB y medir el ancho de banda de la tarjeta PCIe e InfiniBand. Este proceso duró mucho tiempo (unos 15 minutos) para garantizar que se encontrara el enlace InfiniBand que vibraba.

Ejecute una ejecución de diagnóstico de múltiples nodos para verificar la capacidad de inicialización de NCCL y si se detiene aleatoriamente. Si hay pausas, nuestro código NCCL bifurcado agrega registros adicionales. Esto tarda de 12 a 24 horas en detectar un problema, por lo que normalmente solo lo ejecutamos en nodos nuevos o cuando sospechamos que hay un problema.

Verifique la exportación de DCGM para ver si hay eventos de aceleración del reloj de la GPU (excluyendo los esperados gpu_idle y power_cap). Para verificar estos eventos de energía, la mejor manera es ejecutar un entrenamiento de múltiples nodos que verifique todas las GPU, tarjetas InfiniBand, CPU y discos simultáneamente.

Diagnosticar problemas comunes de entrenamiento

Una vez que el hardware funcione correctamente, puede comenzar la capacitación.

Esta sección compartirá algunos pasos de depuración específicos e información basada en nuestra experiencia ejecutando entrenamiento de modelos de lenguaje grandes en nuestro clúster.

Fallo al iniciar

En cierto modo, este es el mejor error que puedes encontrar porque es (teóricamente) fácil de reproducir e iterar.

Primero verificamos que nuestro código se estuviera ejecutando en la versión, configuración y variables de entorno correctas. Aunque es básico, consideramos que esto es fundamental: garantizar que el proceso de capacitación inicial sea reproducible y fácil de verificar. Una razón es que las abstracciones intermedias como el almacenamiento en caché de imágenes de Docker o las configuraciones secretas opacas pueden causar confusión.

Otra verificación básica que realizamos es asegurarnos de que todas las máquinas estén en línea y que los seguimientos de la pila o los registros emitidos se puedan agregar e inspeccionar fácilmente. Usamos las pilas de software Loki, Prometheus y Grafana, pero cualquier herramienta SaaS de seguimiento o agregación de registros adecuada servirá. Debido a que estas ejecuciones de entrenamiento son sincrónicas y de naturaleza distribuida, el primer error a menudo conduce a una cascada de errores no relacionados. En este caso, las comprobaciones de estado también pueden ayudar a detectar inmediatamente errores como un disco duro dañado o una GPU faltante o no válida.

Creamos un sistema que se reinicia automáticamente en caso de falla, lo que hace que la agregación de registros y errores sea aún más importante para evitar errores confusos provenientes de diferentes reinicios. Algunos errores comunes que encontramos incluyen:

1. Errores como "El orden de avance difiere según los rangos: el rango 0 reúne todos 43 parámetros, mientras que el rango 1228 reúne 1 parámetro". Descubrimos que esta era una característica extraña de la implementación de datos paralelos completamente fragmentados (FSDP) de PyTorch, que se resolvió con un reinicio.

2. Error de GPU sin memoria (OOM), que se ve así: "CUDA sin memoria. Se intentó asignar..." Al verificar nuestra configuración y código varias veces y deshacer modificaciones recientes del código (debido a especificaciones incorrectas del dispositivo PyTorch durante inicio y resultando en un uso excesivo de GPU#0), solucionamos estos problemas.

3. Errores de CPU/RAM sin memoria (OOM): estos errores no son fáciles de encontrar en el registro de errores y generalmente se pueden detectar a través del registro dmesg del host fuera del contenedor Docker. Cuando OOM Killer llama para detener un proceso bifurcado o un par de red, podemos ver que se manifiestan principalmente como CalledProcessError o ConnectionError. Cuando se detecta una llamada de OOM Killer desde dmesg, preferimos simplemente abandonar la verificación de estado y reiniciar el cuadro. También verificamos nuestras rutas de código para una recolección de basura manual adecuada (hay una sección a continuación sobre cómo deshabilitar esto) y también verificamos si hubo intentos inesperados de realizar cálculos o mover tensores a la CPU.

Choque durante el entrenamiento

La primera prioridad es automatizar el sistema para que pueda volver a ejecutar automáticamente todas las comprobaciones de estado y luego reiniciarlo si no se encuentra un host en mal estado. Encontramos algunos errores de hardware aleatorios, incluidos errores Xid y SXid. Estos errores podrían provocar que la ejecución fallara sin emitir un seguimiento de pila de Python significativo; Algunos problemas, como la reasignación de filas, se pueden recuperar reiniciando. Otros problemas, como los errores ECC no corregibles, a menudo requieren mantenimiento de hardware o piezas de repuesto.

Además, observamos que los datos de entrenamiento mal formados también pueden causar fallas. Por ejemplo, si hay un documento muy grande en el corpus, puede provocar un error de falta de memoria en la GPU o la CPU. Para evitar este problema, utilizamos un cargador de datos totalmente determinista, lo que hace que cada falla sea fácilmente reproducible al vincularla a una época o número de paso. Descubrimos que deshabilitar la carga de datos o reemplazar datos falsos (como datos totalmente cero) ayuda a confirmar si la causa principal del error son los datos.

Por último, también puede resultar útil registrar estadísticas generales de salud de los nodos y de la red mediante métodos de agregación de métricas. Problemas como una breve desconexión de Ethernet o poco espacio en disco pueden no aparecer como mensajes de error útiles, pero pueden correlacionarse fácilmente con los datos recopilados.

Colgar sin seguimiento de pila (puede haber problemas de tiempo de espera más adelante)

Debido a la falta de información útil sobre estos temas y la dificultad de reproducirlos de manera confiable, depurar este tipo de errores puede resultar frustrante.

Uno de los tipos de errores más memorables va acompañado de mensajes de error como este:

El perro guardián detectó el tiempo de espera de la operación colectiva: WorkNCCL (SeqNum=408951, OpType=_ALLGATHER_BASE, … , Timeout (ms)=600000) se ejecutó durante 600351 milisegundos antes de agotarse el tiempo de espera

Y todos los trabajadores de GPU en la ejecución de capacitación emitieron dichos mensajes de error.

Esto significa que uno o más hosts no pudieron completar la operación NCCL o las conexiones NCCL e InfiniBand fallaron, lo que provocó que todos los demás hosts quedaran bloqueados en una operación tensor al mismo tiempo hasta que se alcanzara el tiempo de espera NCCL_TIMEOUT. Desafortunadamente, debido a la naturaleza de la biblioteca de software NCCL, es difícil encontrar qué host tiene el problema.

Hemos realizado algunas modificaciones en el registro de la biblioteca de software NCCL; consulte nuestra versión bifurcada: https://github.com/boweiliu/nccl. Esto puede revelar mejor los mensajes u operaciones que se realizan cuando ocurre un bloqueo y, por lo tanto, determinar qué host o GPU puede estar impidiendo que se ejecute.

Tenga en cuenta que para identificar hosts que se comportan mal, a menudo necesitamos determinar qué hosts no generan ciertos mensajes de registro. La ausencia de dichos mensajes indica que el trabajador de este host se ha retrasado o ha fallado.

Otras situaciones que no responden y no tienen mensajes de error disponibles generalmente están relacionadas con problemas relacionados con el hardware, como los errores Xid/SXid/ECC mencionados anteriormente que hacen que el controlador NVIDIA o el controlador de comunicación NVIDIA Docker se bloqueen. Para distinguir los bloqueos de NCCL de los bloqueos del conductor y las condiciones de carrera o los interbloqueos en el código Python, utilizamos herramientas como Py-Spy y GNU Project Debugger (GDB) para depurar los procesos estancados encontrados en tiempo real. Se descubrió un problema específico al utilizar este enfoque: debido a un error de configuración en los subprocesos de Python, no pudimos iniciar correctamente ocho procesos de GPU NCCL multiproceso en algunos hosts, que encontraron una condición de carrera en la etapa del código de inicialización antes de PyTorch.

Desaceleración del entrenamiento (medida por MFU)

La falta de herramientas hace que este tipo de problemas sea aún más frustrante que el anterior. Además de utilizar Py-Spy, inspección de seguimiento de pila y GDB, también empleamos NVIDIA Nsight y herramientas de creación de perfiles, algunas de las cuales son difíciles de usar en entornos altamente distribuidos.

Desafortunadamente, hay muchas razones para una desaceleración general o una velocidad menor que la del modelo de utilización de punto flotante (MFU) demostrado anteriormente.

En primer lugar, resulta útil comprobar la configuración, el código y las variables de entorno varias veces. Los errores que hemos experimentado incluyen ejecutar el modelo incorrecto, tamaño de lote incorrecto, configuraciones UFM o NCCL incorrectas y errores CUDA_DEVICE_MAX_CONNECTIONS. Esto dará como resultado un rendimiento subóptimo.

También nos resulta útil medir MFU instantáneas (es decir, por lote) (en lugar de promedios suavizados o en ventana), ya que las curvas MFU no suavizadas a menudo ayudan a diagnosticar clases de problemas. Los problemas que hacen que el entrenamiento se ralentice incluyen:

Comience a entrenar inmediatamente desde una MFU muy baja (menos de una décima parte de lo esperado) y manténgase estable

Lo más probable es que se trate de un problema de hardware con la conexión de red InfiniBand, como un fallo de un conmutador de capa T2 o T3. Los problemas de hardware entre la GPU y la NIC también pueden causar esta situación, por lo que dmesg informará un error como este: carriles PCIe x16 limitados por...

Comience a entrenar inmediatamente desde el 30% de la MFU esperada y manténgalo estable

Esto podría deberse a una configuración GDR incorrecta en un host (memoria de igual NVIDIA) o a variables de entorno GDR incorrectas.

Comience a entrenar inmediatamente desde aproximadamente el 60-80% de la MFU esperada y manténgalo estable

La causa más común es una calidad de enlace InfiniBand deficiente o defectuosa, específicamente una falla relacionada con la NIC de InfiniBand en una sola GPU, lo que hace que NCCL intente enrutar el tráfico a través de NVLink nativo y usar la NIC en otra GPU en el mismo host. La aceleración de la CPU también puede causar este problema, que requiere ajustar la configuración del BIOS en algunos hosts.

Gran desaceleración repentina (diez veces menor) al procesar ciertos lotes de datos, y esto sucede con bastante frecuencia

Básicamente se trata de puntos de control o evaluación; esto se puede verificar verificando el número de épocas o pasos. Es molesto que si configura una alarma automática cuando la MFU es anormal, aparecerán muchas falsas alarmas.

Gran desaceleración repentina (caída 10 veces mayor) al procesar ciertos lotes de datos

Esto sucede de forma aleatoria y bastante rara (aproximadamente una vez cada 15 minutos) y es seguido inmediatamente por un retorno completo a una buena MFU.

La causa más común parece ser que otras cargas de trabajo con uso intensivo de CPU están programadas para un host en ejecución. Descubrimos que, en lugar de crear herramientas de creación de perfiles para identificar hosts específicos, era más fácil monitorear aproximadamente la CPU mediante PID. La causa pueden ser problemas ocasionales de conectividad de red, como cuellos de botella en el cargador de datos. Monitoreamos cargas de datos, puntos de control y métricas para cualquier código que no sea NCCL y agregamos registros de sincronización del código Python, que demostraron ser muy confiables.

MFU se ralentiza gradualmente durante el funcionamiento, pero vuelve al 100% después de cada reinicio

En teoría, la causa podría ser la acumulación de calor en el interruptor, pero nunca hemos visto que esto suceda. Sin embargo, utilizamos los perfiladores de Python y NVIDIA para determinar que la causa de la degradación del rendimiento parece ser la recolección automática de basura.



Al depurar estas desaceleraciones, descubrimos que era casi seguro que el rendimiento disminuiría periódicamente. A medida que avance la formación, esta disminución tendrá un impacto cada vez mayor en la informática distribuida. Esto nos llevó a sospechar que la causa de la caída podría estar relacionada con la recolección automática de basura, una conjetura que verificamos mediante análisis y pruebas. Cuando deshabilitamos la recolección automática de basura y configuramos la recolección de basura solo en intervalos específicos en todos los hosts, esta "caída" del rendimiento desapareció.

Utilizamos un algoritmo de entrenamiento distribuido síncrono FSDP basado en ZeRO-3. Durante una operación de bloqueo, un único proceso de trabajo que ejecuta la recolección de basura puede ralentizar a todos los demás trabajadores. Si tiene cientos de procesos de trabajo, esto puede provocar ralentizaciones importantes.

El rendimiento es bueno al principio, luego cae repentinamente (al 70 % del esperado) y continúa a alta frecuencia (cada 15 segundos).

Observamos que esto está relacionado con "motivos de aceleración del reloj" en las GPU de NVIDIA, que se pueden resolver con la configuración adecuada para NVIDIA DCGM. Los problemas térmicos (alta temperatura de la GPU o falla del ventilador de enfriamiento del host/efectividad reducida) o fallas en la fuente de alimentación pueden causar este problema. Además, cuando maximizamos la utilización de 8 GPU y 8x NIC InfiniBand junto con CPU/RAM/disco, algunos de nuestros hosts con hardware de fuente de alimentación específico tienen problemas de voltaje, pero solo los usan todos (generalmente solo en Esto solo ocurre durante el carrera de entrenamiento real).

Buen rendimiento pero más ruido de lo habitual (variación del ruido blanco de alta frecuencia entre el 90% y el 100% del MFU esperado)

Esto también está relacionado con el hardware InfiniBand, pero generalmente se debe a cierto grado de degradación del rendimiento o fluctuación en los enlaces superiores de la red, en lugar de los hosts menos redundantes de la capa T2.

Desafortunadamente, muchos de estos problemas son difíciles de identificar en un host específico, y los problemas relacionados con InfiniBand son particularmente difíciles de identificar debido a la naturaleza consciente de la topología de la tecnología de conmutador InfiniBand. InfiniBand parece favorecer los hosts adyacentes en el diseño de árbol grueso de InfiniBand, mientras que UFM puede enrutar paquetes a velocidades de enlace asimétricas.

El siguiente es un resumen/diagrama de flujo/lista de verificación simple para depurar problemas de rendimiento:

¿Este sistema funcionó correctamente antes?

¿Qué cambios ha realizado recientemente (como fusionar código, actualizar controladores)?

¿El host que está ejecutando está sano? ¿Todos sus servicios dependientes se ejecutan normalmente, incluido SaaS de terceros, como Docker Hub, GitHub, etc.?

¿Puede estar seguro de que el código, el entorno, la configuración, la versión, la lista de hosts, el orden de clasificación y la semilla aleatoria que está ejecutando ahora son exactamente los mismos que la última vez? (Si tal verificación pudiera implementarse).

¿Es reproducible el problema?

¿Cómo se relaciona con otras cosas? ¿Otros procesos? ¿Tareas diarias programadas en crontab? ¿Anfitrión o indicador DCGM o UFM?

¿Su herramienta mide estas métricas correctamente?

¿El problema persiste cuando se ejecuta una versión simplificada del código (usando modelos más pequeños, datos falsos, sin guardar ni cargar puntos de control)?

Mejorar las herramientas de infraestructura.

Una vez que haya completado los pasos anteriores, estará en camino de lograr un buen rendimiento al entrenar su modelo... al menos hasta que algo se rompa.

Esta sección presenta algunas de las herramientas y sistemas utilizados para garantizar una capacitación constante, aunque idealmente requiera la menor intervención humana posible. Como somos un equipo pequeño, no tenemos suficiente mano de obra para realizar reparaciones manuales, por lo que también queremos automatizar este proceso tanto como sea posible.

Casi todos los problemas que encontramos durante la capacitación pueden atribuirse a fallas de la máquina o de un componente de la red. Estos tipos de fallas son comunes en clústeres grandes, por lo que nuestro enfoque es desactivar automáticamente la máquina y los componentes de red que fallan y enviar una solicitud de reparación.

mal funcionamiento de la máquina

Desarrollamos un sistema que se reinicia automáticamente desde el punto de control más reciente si una ejecución falla. En este proceso de reinicio, primero se verifica el estado de cada máquina disponible y luego cada máquina se clasifica según los resultados de la verificación de estado que pasa, luego se intenta reiniciar el entrenamiento en la máquina más saludable;

Fallo del componente de red

Todas las fallas de red que observamos fueron detectadas por UFM y registradas en el registro de eventos de UFM, por lo que la respuesta fue simple: analizar el registro de UFM y tomar las medidas adecuadas.

El sistema de eventos de la UFM es muy complejo y contiene decenas de tipos de eventos. En la práctica, sin embargo, encontramos que sólo unos pocos eventos eran problemáticos, principalmente relacionados con fallas de enlace o técnicas de error de alto símbolo. Después de identificar estos eventos, podemos escribir scripts para analizar el registro de eventos de UFM, deshabilitar los enlaces y puertos relacionados con los eventos recientes, solicitar órdenes de trabajo de mantenimiento para estos componentes de la red y volver a habilitar estos componentes una vez completado el mantenimiento.

sistema de archivos espejo local

Para estas grandes capacitaciones distribuidas, se ha descubierto desde hace mucho tiempo que la velocidad del intercambio de datos entre el clúster y Ethernet es un cuello de botella. El ancho de banda de una conexión Ethernet compartida es de aproximadamente 10 Gbit/s; este ancho de banda puede saturarse rápidamente si cientos de trabajadores descargan conjuntos de datos y modelan puntos de control simultáneamente.

Con este fin, decidimos construir un sistema de archivos local dentro de nuestro clúster como espejo para el almacenamiento en la nube, que es esencialmente un espacio de caché que puede reducir la cantidad de archivos leídos desde S3. Para tener en cuenta la rotación del clúster (es decir, cuando una máquina se desactiva o reemplaza por motivos de mantenimiento), tenemos tres copias de cada archivo y utilizamos hash consistente para distribuir uniformemente la carga para maximizar el rendimiento durante la rotación del clúster. Dado que el clúster tiene espacio en disco limitado, tuvimos que desarrollar herramientas para rastrear el ciclo de vida de los archivos y eliminar archivos que ya no eran útiles.

Registro Docker distribuido local

Usamos Kraken, que es un excelente software de código abierto para transferir imágenes de Docker punto a punto. Casi no tuvimos problemas con el software, lo cual nos sorprendió bastante, considerando la complejidad de nuestras tareas e implementación. Dirección de la herramienta: https://github.com/uber/kraken

Varias herramientas de seguimiento del rendimiento

Configuramos el analizador Torch predeterminado y los sistemas Nsight de NVIDIA. Esto último nos ayuda a comprender el tiempo exacto requerido para los pases de avance/retroceso y la comunicación NCCL, y además nos ayuda a determinar si un tamaño de modelo determinado y una cantidad de trabajadores se convertirán en un cuello de botella. Sin embargo, Nsight Systems es un poco difícil de usar porque requiere ejecutar Docker en modo privilegiado, lo que requiere deshabilitar los controles de seguridad relacionados con los eventos de monitoreo del rendimiento, y guardar su configuración a menudo requiere detener todo el proceso de capacitación.

Además, hemos escrito herramientas para detectar lotes de entrenamiento lentos y comprender sus posibles causas. Esto nos pareció útil. La herramienta más útil monitorea cuánto tiempo toma cada lote y descarta el seguimiento de la pila del trabajador si un lote es demasiado lento, lo que facilita la búsqueda de hosts con problemas menores de hardware o software.

Divida las máquinas en diferentes grupos para localizar hosts fallidos

En los primeros meses de uso del clúster (cuando las comprobaciones de estado no eran tan exhaustivas como lo son ahora), a menudo nos topábamos con una situación en la que ocurría una falla mientras entrenábamos en un grupo de máquinas, pero no estaba claro qué máquina tenía el problema. . pregunta. Para encontrar hosts defectuosos, desarrollamos herramientas que facilitan dividir un conjunto de máquinas en diferentes grupos y ejecutar capacitaciones más pequeñas en cada grupo de máquinas.

Por ejemplo, si falla un entrenamiento en 48 máquinas, ejecute un entrenamiento más pequeño en 6 grupos de 8 máquinas cada uno y luego ejecute el entrenamiento más pequeño en 8 grupos de 6 máquinas cada uno. Normalmente, sólo fallará una ejecución de las dos fases, lo que nos da confianza para concluir que una máquina que falla en ambas fases está defectuosa.

Reflexión y lecciones aprendidas

Durante el proceso de instalación y mantenimiento de la infraestructura, aprendimos algunas lecciones útiles:

Un enfoque útil es cambiar la ubicación de las máquinas. En tiempo de ejecución, puede resultar útil utilizar entre un 10 % y un 20 % más de máquinas de las necesarias para que la capacitación pueda reiniciarse fácilmente en caso de que falle la máquina. Configurar la red de clústeres para que cada máquina esté estrechamente conectada entre sí nos permite utilizar cualquier subconjunto funcional de esas máquinas.

Vale la pena escribir pruebas y soluciones automatizadas para cada falla de hardware o software que encuentre, porque todos los problemas encontrados en la capacitación volverán a ocurrir. De manera similar, para cada mensaje de error ambiguo, vale la pena escribir una herramienta que explique mejor el error.

La reproducibilidad es clave para una buena investigación científica. Uno de los grandes principios que adoptamos de inmediato fue: "Sólo cambia una cosa a la vez", incluso en las cosas más simples.

Confía, pero también verifica. Siempre que incorporamos herramientas externas o incorporamos gente nueva (ya sea dentro o fuera de la empresa), verificamos dos veces lo que afirman, especialmente si los pasos posteriores dependen de esas afirmaciones.

Resumir

La formación de grandes modelos de lenguaje requiere una infraestructura compleja desde el principio. Elegimos involucrarnos profundamente en los detalles de la configuración de la infraestructura porque creemos que es importante comprender completamente los sistemas que operamos y porque creemos que es más eficiente hacerlo.

Ahora, después de haber pasado por el proceso, nos alegra haber adoptado este enfoque: tener un control total sobre nuestra infraestructura y la capacidad de depurar fácilmente en todos los niveles de abstracción ha demostrado ser de un valor fundamental. Si bien este proceso requirió mucha supervisión e iteración, nos permitió obtener una comprensión profunda del flujo de trabajo subyacente, crear un conjunto de herramientas para garantizar la salud del host, aprender cómo automatizar el sistema para garantizar una capacitación continua y fluida y, en última instancia, construir un Conjunto de infraestructura que nos permite entrenar de forma rápida e iterativa modelos de lenguajes de vanguardia.

Este proceso de construcción de infraestructura refleja nuestra metodología básica para investigar y construir agentes de IA: explorar los detalles, mejorar continuamente los procesos existentes y construir herramientas y sistemas útiles para permitir que nuestro equipo motivado aborde desafíos más grandes.