notícias

Do bare metal a um grande modelo com 70 bilhões de parâmetros, aqui está um tutorial e scripts prontos para uso

2024-07-24

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



Selecionado em imbue.com

Autor: Equipe Imbue

Compilação de coração de máquina

Editor: panda

Sabemos que o LLM é treinado em clusters de computadores de grande escala usando dados massivos. A Machine Heart introduziu muitos métodos e tecnologias para auxiliar e melhorar o processo de treinamento do LLM. Hoje, o que queremos compartilhar é um artigo que se aprofunda na tecnologia subjacente e apresenta como transformar um monte de "bare metals" que nem sequer possuem um sistema operacional em um cluster de computadores para treinamento de LLM.

Este artigo vem da Imbue, uma startup de IA que se esforça para alcançar inteligência geral através da compreensão de como as máquinas pensam.

Claro, transformar um monte de "bare metal" sem sistema operacional em um cluster de computador para treinamento de LLM não é um processo fácil, cheio de exploração e tentativa e erro, mas Imbue finalmente treinou com sucesso um LLM com 70 bilhões de parâmetros e acumulados. muitas experiências úteis no processo.

Este artigo fornecerá uma introdução detalhada a todo o processo da equipe de construção de sua própria infraestrutura de treinamento LLM e compartilhará as muitas ferramentas e scripts que eles escreveram para facilitar o monitoramento, a inspeção e a correção de erros.

Se você está interessado em construir sua própria infraestrutura de treinamento LLM ou está curioso sobre como o LLM é feito, vale a pena ler e coletar este artigo.

A seguir está o texto original do artigo da equipe Imbue.

introdução

Nossa pequena equipe de pesquisadores e engenheiros passou vários meses treinando um modelo de 70 bilhões de parâmetros do zero em nossa própria infraestrutura, e o modelo superou os modelos de disparo zero em tarefas relacionadas ao GPT-4o.

Hoje, estamos compartilhando o processo de configuração da infraestrutura necessária: desde a montagem do cluster inicial e instalação do sistema operacional até a configuração da recuperação automática quando erros são encontrados durante o treinamento. Detalhamos os desafios encontrados e as soluções em cada etapa. Além desses aprendizados, também lançaremos muitos dos scripts que desenvolvemos ao longo do caminho para tornar mais fácil para outras equipes criarem infraestrutura estável para o treinamento de seu próprio modelo.

Durante todo o processo, nossa equipe de engenheiros trabalhou com a Voltage Park para preparar clusters de computadores e construir a base para aplicações de produção. Todo este processo inclui:

1. Configure cada máquina

2. Configurar InfiniBand

3. Certifique-se de que a máquina esteja completamente saudável

4. Diagnosticar problemas comuns de treinamento

5. Melhorar as ferramentas de infraestrutura

Cada etapa é descrita em detalhes abaixo.

Antecedentes: Como foi feito

Nosso objetivo ao realizar cálculos é garantir a experimentação rápida com grandes modelos de linguagem. Para fazer isso, precisamos de um grande número de GPUs de alta velocidade e de comunicação de alta velocidade entre essas GPUs.

Este artigo se concentrará em um cluster contendo 4.088 GPUs H100 espalhadas por 511 computadores, ou 8 GPUs por computador. A razão pela qual existem 511 computadores com GPUs é porque algumas conexões precisam ser reservadas para o nó Unified Fabric Manager, cuja função é gerenciar a rede InfiniBand. Nos 511 hosts equipados com GPU, cada GPU está diretamente conectada a uma placa de rede ConnectX-7, que pode transmitir dados a 400 Gbps para qualquer GPU na rede InfiniBand.

Nossa topologia de rede InfiniBand é “totalmente sem bloqueio” em teoria, o que permite que as GPUs se comuniquem entre si em velocidade máxima; Para fazer isso, usamos uma arquitetura de rede InfiniBand de três camadas: switches InfiniBand de três camadas. Com as conexões certas, esse alto nível de rendimento pode ser alcançado em toda a rede. A figura a seguir mostra uma visão geral desta rede InfiniBand:



Observe que a comunicação durante o treinamento da rede ocorre por InfiniBand, não por Ethernet. Embora essas máquinas também estejam conectadas à Ethernet, a função dessa rede é transportar dados como conjuntos de dados e pontos de verificação. Se você usar Ethernet para enviar dados, a velocidade será muito mais lenta porque os dados viajarão primeiro da GPU para a CPU e depois sairão pela placa Ethernet de velocidade de 100 Gbps. Embora também seja possível treinar via Ethernet usando uma tecnologia chamada RDMA over Converged Ethernet (RoCE), isso requer muito trabalho extra tanto do lado do hardware quanto do software e geralmente é menos confiável do que o InfiniBand. Para obter detalhes, consulte este artigo: https://arxiv.org/pdf/2402.15627

Há também uma Ethernet secundária usada apenas para configuração e gerenciamento, fornecendo acesso ao BIOS (Basic Input Output System), fonte de alimentação e outras interfaces de controle para interfaces de máquina de baixo nível. Sem esta rede de gerenciamento, teríamos que configurar manualmente cada nó por meio de um driver USB, teclado e monitor. Para situações com centenas de máquinas, esta não é uma abordagem sustentável.

Alcançar treinamento de alto desempenho neste cluster requer que todos os componentes (InfiniBand, Ethernet, GPU e os próprios nós) funcionem quase perfeitamente. Se alguma dessas mais de 12.000 conexões estiver um pouco instável, isso poderá retardar o treinamento geral.

O restante deste artigo é sobre como fazer tudo funcionar de maneira perfeita e estável.

Processo: como transformar bare metal em um cluster totalmente operacional

Configurar cada máquina

Após estabelecer a conexão Ethernet inicial com o cluster através da rede de gerenciamento, são obtidas credenciais de acesso ao controlador de gerenciamento de placa base (BMC). Um BMC é um processador de serviço dedicado que monitora remotamente sistemas host e geralmente está conectado a uma rede separada. Ele nos permite operar a máquina como se estivéssemos lá pessoalmente e, adicionalmente, fornece APIs para integridade do hardware, configurações do BIOS e gerenciamento de energia.

Com esses componentes instalados, podemos arregaçar as mangas e começar a montar o cluster.

Etapa 0: primeiro configure uma máquina

Começamos instalando o Ubuntu 22.04 em um servidor usando iDRAC (Dell's Baseboard Management Controller) e depois configuramos todo o resto com base neste sistema operacional. Um dos recursos do iDRAC é permitir a instalação e inicialização de imagens ISO do computador local e fornecer um console virtual por meio do navegador. Idealmente, esta é a única etapa de instalação manual do processo.

Etapa 1: Instale o sistema operacional em cada máquina

Depois de configurar a primeira máquina, prossiga com a instalação do software Metal-as-a-Service (MAAS) do Ubuntu para ajudar a configurar os servidores restantes. A ferramenta de inicialização e automação do iDRAC usa o Preboot Execution Environment Protocol (PXE) para instruir cada máquina a inicializar a partir da rede e configurar o MAAS para responder às solicitações de inicialização PXE. Ao realizar uma inicialização inicial da rede, o servidor obtém um IP e um kernel inicial do MAAS por meio do Dynamic IP Allocation Protocol DHCP sem precisar instalar nada na unidade local. Este é o ambiente básico para automatizar instalações repetíveis de sistemas operacionais. Teoricamente basta aguardar o primeiro boot e tudo estará resolvido. Mas, na prática, a integração do MAAS com o BMC não é confiável, então usamos a API do iDRAC para coletar antecipadamente o endereço MAC de cada máquina (um identificador de hardware físico exclusivo).

Ao longo de todo este processo de treinamento, o MAAS é frequentemente o componente mais confiável da pilha vertebral. No entanto, encontramos alguns problemas no início que eram exclusivos da nossa configuração. Por exemplo, ao configurar as primeiras máquinas, não consegui instalar nada via apt devido a problemas de verificação do certificado HTTPS porque os relógios eram muito diferentes. Da mesma forma, uma vez que o servidor MAAS tem que ser responsável por muitas coisas (servidor DHCP, servidor DNS para resolver nomes de host para IPs, proxy HTTP entre o host e o servidor oficial de pacotes Ubuntu, servidor NTP, gerenciamento de configuração cloud-init, um terreno banco de dados verdade usado para conectar o endereço MAC ao IP, ao nome do host e aos metadados personalizados), por isso é difícil para nós resolver esses problemas pela causa raiz. Além disso, há a questão da curva de aprendizado do ciclo de vida da configuração do MAAS, já que o objetivo do design é lidar com a complexidade do gerenciamento de implantações greenfield e a migração gradual de nós e vários estados intermediários de depuração/não íntegros.

Etapa 2: diagnosticar a máquina quebrada

Descobrimos que cerca de 10% das máquinas falharam ao inicializar, principalmente devido a problemas físicos com o servidor. Este é um cenário comum para configurar grandes clusters de GPU. As situações que encontramos incluem: cabos de rede ausentes ou incorretos, problemas de hardware no iDRAC, unidades de fonte de alimentação danificadas, drivers NVME (memória não volátil rápida) danificados, linhas internas ausentes, placas de rede ou GPUs não exibidas. Verificamos automaticamente esses problemas, devolvemos algumas máquinas à Dell para novos testes e enviamos ordens de serviço apropriadas para a equipe do data center. Uma vantagem de configurarmos o cluster nós mesmos é que podemos usar máquinas íntegras imediatamente enquanto aguardamos a manutenção de algumas máquinas.

Etapa 3: Máquina Observável Mínima Viável

Continuamos com as seguintes configurações em cada servidor:

1.Docker (para facilitar a execução de serviços e trabalhos de treinamento)

2. Driver GPU do data center

3. Ferramenta de exportação de nó Prometheus (usada para exportar fluxo de dados de indicador de hardware/sistema operacional estável)

4.Ferramenta de exportação DCGM (usada para exportar dados de indicadores adicionais da GPU NVIDIA, como status da GPU, relógio, utilização)

5. Pool RAIDZ ZFS para todos os drivers de sistema não operacional, que permite que a máquina continue funcionando mesmo se um driver falhar, ao mesmo tempo que fornece compactação transparente gratuitamente (isso é especialmente útil para conjuntos de dados de texto simples e logs repetitivos - relativamente Usando isto ferramenta normalmente aumenta o espaço utilizável em até 10 vezes em comparação com a não utilização desta ferramenta)

Em seguida, executamos diagnósticos básicos da GPU para determinar se a GPU está funcionando corretamente - qualquer coisa que não esteja normalmente levará a problemas de hardware dentro de algumas horas.

Durante esse período, encontramos gargalos de largura de banda ao tentar instalar pacotes em todos os 400 nós simultaneamente. Esta é a primeira vez que recebemos alertas de superaquecimento de alta temperatura em vários componentes implantados em nosso data center. Esses primeiros problemas de aquecimento foram amplamente resolvidos por meio de atualizações de firmware.

Etapa 4: treinamento de GPU de nó único

A próxima etapa é garantir que cada máquina possa lidar com cargas de trabalho reais de GPU por conta própria. Muitas máquinas não conseguem fazer isso e os problemas incluem:

Erros relacionados à GPU, que geralmente podem ser resolvidos reinserindo a placa GPU no slot de placa: Deslize o servidor de 200 libras para fora do rack, remova todos os cabos entre a tampa e a GPU e remova a GPU, reinstale a GPU e, em seguida, reconecte os cabos e empurre o servidor de volta para o rack.

De acordo com os logs do servidor Ubuntu, muitos cabos entre a GPU e o barramento PCIe ou placa de rede emitiram este erro: “largura limitada: x4 <x16”. Depois de atualizar o firmware do barramento do switch PCIe, descobrimos que cerca de um quarto dos hosts precisavam recolocar os cabos PCIe internos - presumivelmente porque os cabos entre o gabinete e a GPU são bastante frágeis, ou seja, sempre que a manutenção for realizada na GPU, esses cabos serão ser empurrado ou puxado para fora.

Houve algumas interrupções diversas que também afetaram vários hosts. A Dell nos ajudou a resolver alguns problemas com uma atualização de firmware:

A unidade NVMe não apresentou falhas, mas travou toda a máquina quando tocada.

Os discos rígidos aparecem em ordem aleatória no Linux, causando confusão no MAAS e fazendo com que o sistema operacional seja instalado na unidade errada.

A leitura da temperatura está errada, o que faz com que o ventilador funcione a toda velocidade o tempo todo. O motivo pode ser um problema com o driver NVIDIA, que é resolvido com o downgrade da versão do driver.

O escalonamento dinâmico da CPU ficou fora de controle, limitando os núcleos funcionais a 2 GHz.

A comunicação direta GPU-GPU (GDR ou GPUDirect RDMA Peer Memory Client) não pode ser aplicada com êxito.

Configurar InfiniBand

Etapa 0: Instale o UFM

Uma vantagem do InfiniBand é seu design centralizado, de modo que toda a rede tenha um único cérebro. Portanto, só precisamos lidar com uma instância dos 320 switches de rede em toda a estrutura da rede. Nossa primeira tarefa foi descobrir qual switch conectava quais máquinas, depois associá-lo ao diagrama de fiação e renomeá-los com base na localização física do switch.

Etapa 1: religação

Inicialmente, o UFM não conseguiu detectar esses 320 switches, muito menos os hosts que deveriam estar presentes na malha. Após consultar nossos parceiros de data center, confirmamos que os switches estavam ligados e conectados, mas ainda não conseguimos detectá-los. Depois de examinar a lista de cabeamento de rede, percebemos que o projeto de nível superior da estrutura da rede estava incorreto: em vez de ser unificada, a estrutura foi dividida em oito redes desconectadas sem nenhum caminho de roteamento comum. Após a religação, adicionamos uma etapa de verificação para verificar se todas as conexões físicas estão consistentes com o novo design.

Passo 2: Dez mil alarmes de temperatura (alerta)

Depois que os problemas de fiação física foram resolvidos, o InfiniBand estabeleceu conexões com êxito com todos os switches InfiniBand na estrutura da rede. No entanto, quase todas as portas do switch começaram a reportar temperaturas excessivas, às vezes ultrapassando os 70°C, mesmo que não estivessem transmitindo dados. Descobrimos que o problema resultava do espaço aberto entre os switches no mesmo rack, o que fazia com que o ar quente fluísse de volta para a frente. Nosso parceiro de data center nos ajudou a diagnosticar rapidamente o problema e desenvolver uma solução adequada.

Etapa 3: 1.800 alarmes

Muitas portas também apresentam altas taxas de erro ou alternam entre estados normais e corrompidos, o que é chamado de "flapping". Esses problemas só surgem quando as portas são realmente utilizadas, por isso são difíceis de detectar antecipadamente porque toda a nossa estrutura consiste em 10.000 links altamente redundantes. Nosso parceiro de data center ajudou a limpar e reinstalar as portas do alarme e desativamos os transceptores de alarme restantes enquanto aguardávamos a substituição.

Embora o InfiniBand seja resiliente a falhas de hardware, quando cerca de 10% da malha começa a falhar, recursos como roteamento adaptativo não funcionam de maneira confiável para compensar a perda ocasional de link.

Durante esse período, executamos com sucesso o treinamento de vários nós usando de 100 a 200 máquinas. Nosso processo é um tanto improvisado: às vezes criamos um conjunto aleatório de nós, observamos seu desempenho e depois tentamos manter o maior número possível deles em execução. Este método nos permite encontrar um subconjunto confiável da estrutura da rede InfiniBand, mas é muito difícil porque cada vez precisamos alterar o conjunto de nós usados ​​para treinamento, alterando assim o link padrão do InfiniBand.

Etapa 4: InfiniBand queima loucamente

Para diagnosticar problemas do InfiniBand com mais eficiência, projetamos uma carga de trabalho para todo o cluster que enviava o máximo de dados possível através de todas as portas da malha simultaneamente. Isso é diferente de executar uma grande carga de trabalho totalmente reduzida em todo o cluster, que requer o uso de NCCL para otimizar a comunicação entre nós individuais usando NVLink para comunicação de GPU por meio de slots de módulo PCIe de servidor (SXM).

Em vez disso, optamos por uma abordagem de força bruta e obtivemos sucesso com facilidade. O UFM começará a emitir alertas quando o volume de transferência de dados na maioria das portas exceder 97% da capacidade teórica e alguns switches ficarão temporariamente inativos. Cada porta que pensávamos ter chegado ao fim do dia era robusta o suficiente, e o restante foi desativado ou removido enquanto se aguardava reparos.

Etapa 5: GPUDirect RDMA

Para permitir a comunicação da GPU sem incorrer em sobrecarga de computação da CPU, habilitamos um recurso chamado GPUDirect RDMA, que permite a comunicação direta entre placas de rede InfiniBand. Isso envolve duas etapas principais:

1. Inicie um módulo de kernel adicional

2. Certifique-se de que o PCIe Access Control Service (ACS) esteja desabilitado para evitar travamentos imediatos (travamentos imediatos)

Etapa 6: Expanda o servidor “ouro”

Para construir um cluster de GPU usando o hardware mais recente, uma regra prática é estar preparado para que aproximadamente 3% de suas máquinas falhem todas as semanas.

No entanto, deve-se notar: nem todas as máquinas têm uma chance uniforme de 3% de falha, mas um pequeno número de máquinas não tratadas apresentam vários problemas repetidamente até serem devidamente reparadas. Isto destaca as vantagens de ter um grande número de máquinas na mesma estrutura de rede. Portanto, em vez de apenas encontrar máquinas aleatórias para executar treinamento em larga escala, como bater em uma toupeira para ver o que quebra, nossa abordagem é focar no dimensionamento de servidores que são conhecidos por serem confiáveis, os servidores “de ouro”.

Etapa 7: Manutenção

A manutenção do InfiniBand envolve principalmente responder a alarmes UFM, substituir cabos e transceptores defeituosos e, ocasionalmente, diagnosticar erros mais difíceis (como falhas de switch). Geralmente há dois fatores que levam à manutenção em grande escala:

1. As atualizações de firmware, especialmente quando apenas metade do cluster tiver concluído a atualização, podem resultar em estado UFM corrompido e exigir uma reinicialização do UFM em todos os switches InfiniBand.

2. As caixas GPU são reiniciadas massivamente ao mesmo tempo, o que pode injetar um grande número de atualizações no estado do UFM e também exigir a reinicialização do serviço UFM.

Certifique-se de que a máquina esteja completamente saudável

Ao longo do caminho, descobrimos diversas maneiras pelas quais máquinas individuais poderiam funcionar mal ou retardar o treinamento. Muitos desses modos de falha não são imediatamente aparentes, por isso escrevemos vários scripts de verificação de integridade para verificar se o host estava suficientemente íntegro. Publicamos o código aqui: https://github.com/imbue-ai/cluster-health

Observe que muitas dessas verificações de integridade são específicas do nosso ambiente de execução e não estão necessariamente relacionadas ao hardware subjacente, nem são necessariamente fáceis de corrigir ou automatizar. Isso ocorreu intencionalmente: para atingir o objetivo geral de preparar nossas máquinas para o treinamento, queríamos um ponto de entrada único que pudesse responder sim ou não de maneira direta e que pudesse resumir uma série de detalhes.

Verificação de integridade da GPU

Verificamos se o número de GPUs estava correto, se a verificação ECC (Error Correction Code) estava habilitada e se não havia erros de ECC. Também verificamos se a topologia NVLink (que conecta GPUs entre si) está funcionando sem erros.

Verificação de integridade do espaço em disco

Verificamos se a utilização do espaço em disco do host excede 95%.

Verificação de integridade do Docker

Verificamos se o Docker pode executar contêineres com a GPU conectada (ou seja, o NVIDIA Container Runtime está funcionando corretamente) e se os contêineres do Docker relacionados ao monitoramento/análise estão ativados e têm as permissões de host corretas.

Verificação de integridade do Dmesg

Verificamos o dmesg em busca de erros de hardware Xids ou SXid (falhas causadas por GPUs NVIDIA ou switches NVIDIA entre GPUs). Também lemos todas as linhas de log dmesg para verificar se todas elas podem ser classificadas na lista Linhas de log comuns/esperadas.

Verificação de integridade do iDRAC

Verificamos erros do iDRAC na máquina, que ignorou mensagens de erro não fatais. Esta é uma verificação específica para computadores Dell, portanto não está incluída em nosso código-fonte aberto.

Verificação de integridade do disco

Verificamos se o zpool está instalado, se o Docker está conectado corretamente a ele e se ele pode realmente acessá-lo sem travar a CPU.

Verificação de integridade da InfiniBand

Verificamos se a taxa de erros do InfiniBand aumentou e/ou se o firmware do driver estava desatualizado.

Verificação de integridade do Nvlink

Verificamos erros de NVLink na máquina. Na prática, isso não parece causar falhas no treinamento, mas pode retardar o treinamento.

Verificação de saúde da RDA

Verificamos se o GDR está habilitado na máquina.

Verificação de integridade do VBIOS

Verificamos se a versão VBIOS da GPU e o firmware da placa base H100 estavam atualizados.

Verificação de saúde de Flint

Usamos flint e hca_self_test para verificar se o driver Mellanox OFED, o firmware da placa de rede e o firmware do transceptor eram das versões corretas e se foram compilados corretamente para o driver NVIDIA.

Verificação de integridade do PSB

Consultamos os dispositivos PCIe para verificar se a velocidade e largura da conexão entre GPU, PSB (PCIe Switch Bus) e placa de rede eram as esperadas. Também verificamos se o firmware do switch está atualizado. Este script foi desenvolvido pela Dell, não pela Imbue, portanto não podemos compartilhá-lo no momento.

Além dessas verificações rápidas de integridade, também realizamos algumas verificações de integridade mais complexas, incluindo:

Inicialize cálculos de matriz por meio do PyTorch e meça a largura de banda do NVLink e a velocidade e memória de cálculo da GPU. Definimos os sinalizadores GDR apropriados para testar InfiniBand e NVLink.

Use ib_write_bw e –use_cuda para enviar dados através da placa IB e medir a largura de banda da placa PCIe e InfiniBand. Esse processo durou muito tempo (cerca de 15 minutos) para garantir que o link instável do InfiniBand fosse encontrado.

Execute uma execução de diagnóstico de vários nós para verificar a capacidade de inicialização do NCCL e se ele trava aleatoriamente. Se houver pausas, nosso código NCCL bifurcado adiciona registro adicional. Isso leva de 12 a 24 horas para detectar um problema, então normalmente só executamos isso em novos nós ou quando suspeitamos de um problema.

Verifique a exportação do DCGM para quaisquer eventos de aceleração do clock da GPU (excluindo gpu_idle e power_cap esperados). Para verificar esses eventos de energia, a melhor maneira é executar um treinamento de vários nós que verifique todas as GPUs, placas InfiniBand e CPUs e discos simultaneamente.

Diagnosticar problemas comuns de treinamento

Assim que o hardware estiver funcionando corretamente, o treinamento poderá começar.

Esta seção compartilhará algumas etapas de depuração específicas e insights com base em nossa experiência na execução de treinamento de grandes modelos de linguagem em nosso cluster.

Falha na inicialização

De certa forma, este é o melhor bug que você pode encontrar porque é (teoricamente) fácil de reproduzir e iterar.

Primeiro verificamos se nosso código estava sendo executado na versão, configuração e variáveis ​​de ambiente corretas. Embora básico, achamos isso fundamental: garantir que o processo de treinamento da startup seja reproduzível e fácil de verificar. Um dos motivos é que abstrações intermediárias, como cache de imagens do Docker ou configurações secretas opacas, podem causar confusão.

Outra verificação básica que realizamos é garantir que todas as máquinas estejam online e que os stack traces ou logs emitidos possam ser facilmente agregados e inspecionados. Usamos as pilhas de software Loki, Prometheus e Grafana, mas qualquer ferramenta SaaS adequada de agregação de log ou rastreamento servirá. Como essas execuções de treinamento são de natureza síncrona e distribuída, o primeiro erro geralmente leva a uma cascata de erros não relacionados. Aqui, as verificações de integridade também podem ajudar a detectar erros imediatamente, como um disco rígido corrompido ou uma GPU ausente ou inválida.

Construímos um sistema que reinicia automaticamente em caso de falha, o que torna a agregação de logs e erros ainda mais importante para evitar erros confusos em reinicializações diferentes. Alguns erros comuns que encontramos incluem:

1. Erros como "A ordem de encaminhamento difere entre as classificações: a classificação 0 reúne 43 parâmetros, enquanto a classificação 1228 reúne 1 parâmetros". Descobrimos que esse é um recurso estranho da implementação Fully Sharded Data Parallel (FSDP) do PyTorch, que foi resolvido com uma reinicialização.

2. Erro de GPU sem memória (OOM), que se parece com isto: "CUDA sem memória. Tentativa de alocar..." Verificando nossa configuração e código várias vezes e desfazendo modificações recentes de código (devido a especificações incorretas do dispositivo PyTorch durante inicialização e resultando no uso excessivo da GPU#0), corrigimos esses problemas.

3. Erros de falta de memória de CPU/RAM (OOM). Esses erros não são fáceis de encontrar no log de erros e geralmente podem ser detectados por meio do log dmesg do host fora do contêiner do Docker. Quando o OOM Killer chama para interromper um processo bifurcado ou peer de rede, podemos ver que eles se manifestam principalmente como CalledProcessError ou ConnectionError. Quando uma chamada OOM Killer é detectada no dmesg, preferimos simplesmente abandonar a verificação de integridade e reiniciar a caixa. Também verificamos nossos caminhos de código para coleta de lixo manual adequada (há uma seção abaixo sobre como desabilitar isso) e também verificamos qualquer tentativa inesperada de fazer cálculos ou mover tensores para a CPU.

Bater durante o treino

A primeira prioridade é automatizar o sistema para que ele possa executar automaticamente todas as verificações de integridade e, em seguida, reiniciar se um host não íntegro não for encontrado. Encontramos alguns erros aleatórios de hardware, incluindo erros Xid e SXid. Esses erros podem causar falha na execução sem emitir um rastreamento de pilha Python significativo; Alguns problemas, como o remapeamento de linhas, podem ser recuperados reinicializando. Outros problemas, como erros de ECC incorrigíveis, geralmente exigem manutenção de hardware ou peças de reposição.

Além disso, observamos que dados de treinamento malformados também podem causar travamentos. Por exemplo, se houver um único documento muito grande no corpus, isso poderá causar um erro de falta de memória na GPU ou CPU. Para evitar esse problema, usamos um carregador de dados totalmente determinístico - tornando cada falha facilmente reproduzível ao ser vinculada a uma época ou número de etapa. Descobrimos que desabilitar o carregamento de dados ou substituir dados falsos (como dados totalmente zero) ajuda a confirmar se a causa raiz do erro são os dados.

Finalmente, também pode ser útil registrar estatísticas gerais de saúde da rede e dos nós por meio de métodos de agregação de métricas. Problemas como uma breve desconexão da Ethernet ou pouco espaço em disco podem não aparecer como mensagens de erro úteis, mas podem ser facilmente correlacionados com os dados coletados.

Pendure sem rastreamento de pilha (pode haver problemas de tempo limite posteriormente)

Devido à falta de informações úteis sobre esses problemas e à dificuldade de reproduzi-los de maneira confiável, a depuração desses tipos de erros pode ser frustrante.

Um dos tipos de erros mais memoráveis ​​é acompanhado por mensagens de erro como esta:

O watchdog detectou o tempo limite da operação coletiva: WorkNCCL (SeqNum=408951, OpType=_ALLGATHER_BASE, …, Tempo limite (ms)=600000) executado por 600351 milissegundos antes do tempo limite

E todos os trabalhadores da GPU na execução de treinamento emitiram essas mensagens de erro.

Isso significa que um ou mais hosts falharam ao concluir a operação NCCL ou as conexões NCCL e InfiniBand travaram, fazendo com que todos os outros hosts ficassem presos em uma operação de tensor ao mesmo tempo até que o tempo limite de NCCL_TIMEOUT fosse atingido. Infelizmente, devido à natureza da biblioteca de software NCCL, é difícil descobrir qual host apresenta o problema.

Fizemos algumas modificações no registro da biblioteca de software NCCL, veja nossa versão bifurcada: https://github.com/boweiliu/nccl. Isso pode revelar melhor as mensagens ou operações que estão sendo executadas quando ocorre uma falha e, assim, determinar qual host ou GPU pode estar impedindo sua execução.

Observe que, para identificar hosts que se comportam mal, geralmente precisamos descobrir quais hosts não estão gerando determinadas mensagens de log. A ausência de tais mensagens indica que o trabalhador neste host ficou para trás ou travou.

Outras situações de falta de resposta e sem mensagens de erro disponíveis geralmente estão relacionadas a problemas relacionados ao hardware, como os erros Xid/SXid/ECC mencionados anteriormente que fazem com que o driver NVIDIA ou o driver de comunicação NVIDIA Docker trave. Para distinguir travamentos de NCCL de travamentos de driver e condições de corrida ou impasses no código Python, usamos ferramentas como Py-Spy e o GNU Project Debugger (GDB) para depurar processos paralisados ​​encontrados em tempo real. Um problema específico foi descoberto usando esta abordagem: devido a um erro de configuração nas configurações do thread Python, não foi possível iniciar corretamente oito processos GPU NCCL multithread em alguns hosts, que encontraram uma condição de corrida no estágio do código de inicialização antes do PyTorch.

Desaceleração do treinamento (medida pelo MFU)

A falta de ferramentas torna este tipo de problema ainda mais frustrante que o anterior. Além de usar Py-Spy, inspeção de rastreamento de pilha e GDB, também empregamos NVIDIA Nsight e ferramentas de criação de perfil, algumas das quais são difíceis de usar em ambientes altamente distribuídos.

Infelizmente, há muitas razões para uma desaceleração geral ou velocidade menor do que o modelo de utilização de ponto flutuante (MFU) demonstrado anteriormente.

Primeiro, é útil verificar variáveis ​​de configuração, código e ambiente diversas vezes. Os erros que enfrentamos incluem a execução do modelo errado, tamanho de lote errado, configurações UFM ou NCCL erradas, erros CUDA_DEVICE_MAX_CONNECTIONS. Isso resultará em um desempenho abaixo do ideal.

Também achamos útil medir MFU instantâneo (ou seja, por lote) (em vez de médias suavizadas ou em janela), uma vez que curvas de MFU não suavizadas geralmente ajudam a diagnosticar classes de problemas. Os problemas que fazem com que o treinamento fique mais lento incluem:

Comece a treinar imediatamente com MFU muito baixo (menos de um décimo do esperado) e mantenha-se estável

Provavelmente, este é um problema de hardware com a conexão de rede InfiniBand, como falha de um switch de camada T2 ou T3. Problemas de hardware entre a GPU e a NIC também podem causar esta situação, para a qual o dmesg reportará um erro como este: PCIe x16 lanes Limited by…

Comece a treinar imediatamente a partir de 30% do MFU esperado e mantenha-se estável

Isso pode ser causado por configurações incorretas de GDR em um host (memória peer NVIDIA) ou variáveis ​​de ambiente GDR incorretas.

Comece o treinamento imediatamente a partir de aproximadamente 60-80% do MFU esperado e mantenha-se estável

A causa mais comum é a qualidade do link InfiniBand ruim ou defeituosa, especificamente uma falha relacionada à NIC InfiniBand em uma única GPU, fazendo com que a NCCL tente rotear o tráfego via NVLink nativo e usar a NIC em outra GPU no mesmo host. A aceleração da CPU também pode causar esse problema, que requer o ajuste das configurações do BIOS em alguns hosts.

Grande lentidão repentina (redução de 10x) ao processar determinados lotes de dados, e isso acontece com bastante frequência

Basicamente, trata-se de pontos de verificação ou avaliação - isso pode ser verificado verificando o número de épocas ou etapas. Irritantemente, se você configurar um alarme automático quando o MFU estiver anormal, muitos alarmes falsos aparecerão.

Enorme lentidão repentina (queda de 10x) ao processar determinados lotes de dados

Isso acontece aleatoriamente e raramente (cerca de uma vez a cada 15 minutos) e é seguido imediatamente por um retorno completo ao bom MFU.

A causa mais comum parece ser que outras cargas de trabalho com uso intensivo de CPU estão agendadas para um host em execução. Descobrimos que, em vez de criar ferramentas de criação de perfil para identificar hosts específicos, era mais fácil monitorar aproximadamente a CPU por PID. A causa pode ser problemas ocasionais de conectividade de rede, como gargalos no carregador de dados. Monitoramos cargas de dados, pontos de verificação e métricas para qualquer código não NCCL e adicionamos registros de temporização de código Python, que provaram ser muito confiáveis.

MFU desacelera gradualmente durante a operação, mas retorna a 100% após cada reinicialização

Teoricamente, a causa poderia ser o acúmulo de calor no switch, mas nunca vimos isso acontecer. No entanto, usamos criadores de perfil Python e NVIDIA para determinar que a causa da degradação do desempenho parece ser a coleta automática de lixo.



Ao depurar essas lentidão, descobrimos que a taxa de transferência quase caía periodicamente. À medida que a formação avança, este declínio terá um impacto crescente na computação distribuída. Isso nos levou a suspeitar que a causa da queda poderia estar relacionada à coleta automática de lixo – uma conjectura que verificamos por meio de análises e testes. Quando desabilitamos a coleta de lixo automática e configuramos a coleta de lixo apenas em intervalos específicos em todos os hosts, essa "queda" de rendimento desapareceu.

Usamos um algoritmo de treinamento distribuído síncrono FSDP baseado em ZeRO-3. Durante uma operação de bloqueio, um único processo de trabalho executando a coleta de lixo pode desacelerar todos os outros trabalhadores. Se você tiver centenas de processos de trabalho, isso poderá causar lentidão significativa.

O desempenho é bom no início, depois cai repentinamente (para 70% do esperado) e continua em alta frequência (a cada 15 segundos)

Observamos que isso está relacionado a “motivos de aceleração do clock” nas GPUs NVIDIA, que podem ser resolvidos com configurações apropriadas para NVIDIA DCGM. Problemas térmicos (alta temperatura da GPU ou falha/eficácia reduzida do ventilador de resfriamento do host) ou falha na fonte de alimentação podem causar esse problema. Além disso, quando maximizamos a utilização de 8 GPUs e 8x NIC InfiniBand junto com CPU/RAM/disco, alguns de nossos hosts com hardware de fonte de alimentação específico têm problemas de tensão, mas só usam todos eles (geralmente apenas em Isso ocorre apenas durante o corrida de treinamento real).

Bom desempenho, mas mais ruído do que o normal (variação de ruído branco de alta frequência entre 90% e 100% do MFU esperado)

Isso também está relacionado ao hardware InfiniBand, mas geralmente é devido a algum grau de degradação de desempenho ou instabilidade nos links mais acima na rede, em vez de nos hosts menos redundantes da camada T2.

Infelizmente, muitos desses problemas são difíceis de identificar em um host específico, e os problemas relacionados ao InfiniBand são particularmente difíceis de identificar devido à natureza consciente da topologia da tecnologia de switch InfiniBand. O InfiniBand parece favorecer hosts adjacentes no design de árvore gorda do InfiniBand, enquanto o UFM pode rotear pacotes em velocidades de link assimétricas.

A seguir está uma lista de verificação simples de resumo/fluxograma/completude para depurar problemas de taxa de transferência:

Este sistema funcionou corretamente antes?

Que mudanças você fez recentemente (como mesclar código, atualizar drivers)?

O host que você está executando está íntegro? Todos os seus serviços dependentes estão funcionando normalmente, incluindo SaaS de terceiros, como Docker Hub, GitHub, etc.?

Você pode ter certeza de que o código, o ambiente, a configuração, a versão, a lista de hosts, a ordem de classificação e a semente aleatória que você está executando agora são exatamente os mesmos da última vez? (Se tal verificação pudesse ser implementada.)

O problema é reproduzível?

Como isso se relaciona com outras coisas? Outros processos? Tarefas agendadas diariamente pelo crontab? Host ou indicador DCGM ou UFM?

Sua ferramenta mede essas métricas corretamente?

O problema persiste ao executar uma versão simplificada do código (usando modelos menores, dados falsos, sem salvar ou carregar pontos de verificação)?

Melhore as ferramentas de infraestrutura

Depois de concluir as etapas acima, você estará no caminho certo para obter um bom desempenho ao treinar seu modelo... pelo menos até que algo quebre.

Esta seção apresenta algumas das ferramentas e sistemas usados ​​para garantir um treinamento consistente, embora, idealmente, exija o mínimo de intervenção humana possível. Por sermos uma equipe pequena, não temos mão de obra suficiente para realizar reparos manuais, por isso também queremos automatizar esse processo ao máximo.

Quase todos os problemas que encontramos durante o treinamento podem ser atribuídos a falhas de máquinas ou componentes de rede. Esses tipos de falhas são comuns em clusters grandes, portanto, nossa abordagem é desabilitar automaticamente a máquina e os componentes de rede com falha e enviar uma solicitação de reparo.

mau funcionamento da máquina

Desenvolvemos um sistema que reinicia automaticamente a partir do ponto de verificação mais recente se uma execução falhar. Neste processo de reinicialização, primeiro a integridade de cada máquina disponível é verificada e, em seguida, cada máquina é classificada com base nos resultados da verificação de integridade que ela passa e, em seguida, é feita uma tentativa de reiniciar o treinamento na máquina mais íntegra.

Falha de componente de rede

Todas as falhas de rede que observamos foram detectadas pelo UFM e registradas no log de eventos do UFM, portanto a resposta foi simples: analise o log do UFM e tome as medidas apropriadas.

O sistema de eventos UFM é muito complexo e contém dezenas de tipos de eventos. Na prática, entretanto, descobrimos que apenas alguns eventos eram problemáticos, principalmente relacionados a falhas de links ou técnicas com altos erros de símbolos. Depois de identificar esses eventos, podemos escrever scripts para analisar o log de eventos do UFM, desabilitar os links e portas relacionados aos eventos recentes, solicitar ordens de serviço de manutenção para esses componentes de rede e reativar esses componentes após a conclusão da manutenção.

sistema de arquivos espelhado local

Para esses grandes treinamentos distribuídos, descobriu-se há muito tempo que a velocidade de troca de dados entre o cluster e a Ethernet é um gargalo. A largura de banda de uma conexão Ethernet compartilhada é de aproximadamente 10 Gbit/s; essa largura de banda pode ficar saturada rapidamente se centenas de trabalhadores baixarem conjuntos de dados e modelarem pontos de verificação simultaneamente.

Para tanto, decidimos construir um sistema de arquivos local dentro de nosso cluster como um espelho para armazenamento em nuvem, que é essencialmente um espaço de cache que pode reduzir a quantidade de arquivos lidos do S3. Para contabilizar a rotatividade do cluster (ou seja, quando uma máquina é desativada ou substituída por motivos de manutenção), temos três cópias de cada arquivo e usamos hashing consistente para distribuir uniformemente a carga para maximizar o desempenho durante a rotatividade do cluster. Como o cluster tem espaço em disco limitado, tivemos que desenvolver ferramentas para rastrear o ciclo de vida dos arquivos e eliminar arquivos que não eram mais úteis.

Registro Docker distribuído localmente

Usamos o Kraken, que é um ótimo software de código aberto para transferência de imagens Docker ponto a ponto. Quase não tivemos problemas com o software, o que nos surpreendeu bastante, dada a complexidade das nossas tarefas e implementação. Endereço da ferramenta: https://github.com/uber/kraken

Várias ferramentas de monitoramento de desempenho

Configuramos o analisador Torch padrão e os sistemas Nsight da NVIDIA. Este último nos ajuda a entender o tempo exato necessário para passagens diretas/reversas e comunicação NCCL, além de nos ajudar a determinar se um determinado tamanho de modelo e número de trabalhadores se tornará um gargalo. No entanto, o Nsight Systems é um pouco difícil de usar porque requer a execução do Docker em modo privilegiado, o que requer a desativação das verificações de segurança relacionadas aos eventos de monitoramento de desempenho, e salvar sua configuração geralmente requer a interrupção de todo o processo de treinamento.

Além disso, escrevemos ferramentas para detectar lotes de treinamento lentos e compreender suas possíveis causas. Achamos isso útil. A ferramenta mais útil monitora quanto tempo cada lote leva e descarta o rastreamento de pilha do trabalhador se um lote for muito lento – facilitando a localização de hosts com pequenos problemas de hardware ou software.

Divida as máquinas em grupos diferentes para localizar hosts com falha

Nos primeiros meses de uso do cluster (quando as verificações de integridade não eram tão completas como são agora), frequentemente nos deparamos com uma situação em que ocorria uma falha durante o treinamento em um grupo de máquinas, mas não estava claro qual máquina tinha o problema. . pergunta. Para encontrar hosts defeituosos, desenvolvemos ferramentas que facilitam a divisão de um conjunto de máquinas em grupos diferentes e a execução de treinamentos menores em cada grupo de máquinas.

Por exemplo, se um treinamento executado em 48 máquinas falhar, então execute um treinamento menor em 6 grupos de 8 máquinas cada e, em seguida, execute o treinamento menor em 8 grupos de 6 máquinas cada. Normalmente, apenas uma execução das duas fases falhará, o que nos dá confiança para concluir que uma máquina que falha em ambas as fases está com defeito.

Reflexão e lições aprendidas

Durante o processo de configuração e manutenção da infraestrutura, aprendemos algumas lições úteis:

Uma abordagem útil é trocar a localização das máquinas. Em tempo de execução, pode ser útil usar de 10 a 20% mais máquinas do que o necessário para que o treinamento possa ser facilmente reiniciado no caso de falha da máquina. Configurar a rede de cluster para que cada máquina esteja firmemente conectada a todas as outras máquinas nos permite usar qualquer subconjunto funcional dessas máquinas.

Vale a pena escrever testes e soluções automatizadas para cada falha de hardware ou software que você encontrar, porque todos os problemas encontrados no treinamento ocorrerão novamente. Da mesma forma, para cada mensagem de erro ambígua, vale a pena escrever uma ferramenta que explique melhor o erro.

A reprodutibilidade é fundamental para uma boa pesquisa científica. Um dos grandes princípios que adotamos imediatamente foi: “Mude apenas uma coisa de cada vez”, mesmo nas coisas mais simples.

Confie, mas também verifique. Sempre que trazemos ferramentas externas ou contratamos novas pessoas (seja de dentro ou de fora da empresa), verificamos novamente o que elas afirmam, especialmente se as etapas subsequentes dependerem dessas afirmações.

Resumir

O treinamento de grandes modelos de linguagem requer infraestrutura complexa desde o início. Optamos por nos envolvermos profundamente nos detalhes da configuração da infraestrutura porque acreditamos que é importante compreender plenamente os sistemas que operamos e porque acreditamos que é mais eficiente fazê-lo.

Agora, depois de passar pelo processo, estamos felizes por termos adotado essa abordagem – ter controle total sobre nossa infraestrutura e a capacidade de depurar facilmente em todos os níveis de abstração provou ser de valor crítico. Embora esse processo exigisse muita supervisão e iteração, ele nos permitiu obter uma compreensão profunda do fluxo de trabalho subjacente, construir um conjunto de ferramentas para garantir a integridade do host, aprender como automatizar o sistema para garantir um treinamento contínuo e tranquilo e, por fim, construir um Conjunto de infraestrutura que nos permite treinar modelos de linguagem de ponta de forma rápida e iterativa.

Este processo de construção de infraestrutura reflete a nossa metodologia básica para pesquisar e construir agentes de IA: explorar os detalhes, melhorar continuamente os processos existentes e construir ferramentas e sistemas úteis para permitir que a nossa equipa motivada enfrente desafios maiores.