Como desenvolvemos os LLMs de última geração da DeepL com FP8 para treinar e inferência

Quando a DeepL implementou o nosso atual NVIDIA DGX SuperPOD com 544 GPUs NVIDIA H100 Tensor Core, não obtivemos apenas um grande aumento na capacidade de computação. O H100 também introduz suporte nativo para tipos de dados de ponto flutuante de 8 bits (FP8), por meio de uma nova geração de Tensor Cores, que permitem que a GPU execute multiplicações matriciais e outras operações tensoriais com precisão FP8. Ao calcular multiplicações de matrizes em FP8, podemos aumentar o rendimento ao treinar e implementar os nossos Modelos de Linguagem Grande (LLMs), uma vez que a maior parte dos cálculos envolvidos nos LLMs modernos assume a forma de multiplicações de matrizes.

A mudança dos cálculos de precisão de 16 bits para 8 bits teve um impacto significativo no desenvolvimento da próxima geração de LLMs da DeepL. Isso permite-nos construir modelos de IA linguística muito maiores, com muito mais parâmetros que proporcionam melhorias significativas na qualidade quando avaliados por especialistas em linguística, mas dentro da mesma janela de latência para inferência de produção. Isso significa traduções que superam os nossos modelos anteriores em 1,4 vezes para idiomas europeus e 1,7 vezes para combinações de idiomas mais complexas, como inglês e japonês, mas que entregam resultados com a mesma rapidez. Isso também significa que os nossos modelos podem lidar com um número maior de solicitações em mais recursos e funções, sem comprometer a experiência do utilizador.

Em outras palavras, o treinamento e a inferência do FP8 desempenharam um papel central na expansão da IA linguística do DeepL.

Nesta publicação, pretendemos explicar a jornada que percorremos para aplicar o FP8 para treinar e inferência, compartilhar algumas das ferramentas e técnicas que sustentam esse sucesso e fornecer uma visão geral dos resultados que geramos em termos de desempenho de treinamento e inferência ao longo do caminho. 

Qual é a diferença entre os formatos BF16 e FP8?

A explicação simples da diferença entre BFloat16 (BF16) e FP8 é que o último utiliza metade dos bits para expressar valores. Efetivamente, o BF16 utiliza as 16 posições disponíveis em dois bytes de 8 bits cada. O FP8 utiliza apenas um byte. 

O número de bits disponíveis determina a precisão com que é possível implementar os elementos mantissa e expoente dos números de ponto flutuante na notação científica. BF16 possui 1 bit de sinal, 8 bits para o expoente e 7 bits para a mantissa. O FP8 possui metade dos bits disponíveis, com 1 bit de sinal e 7 bits divididos entre o expoente e a mantissa. Devido a isso, possui um alcance menor e uma precisão inferior em relação ao BF16. Pode representar um intervalo mais restrito e menos números dentro desse intervalo.

Por exemplo, digamos que pretendemos representar a idade da Terra em milhares de milhões de anos (aproximadamente 4,543). Em BF16, podemos representar isso precisamente como 0100000010010001.  

Que tal representar esse número em FP8? Na verdade, existem dois formatos FP8 à sua escolha: E4M3 e E5M2. As letras e os números aqui representam a forma como os bits são distribuídos entre o expoente (E) e a mantissa (M). Quanto mais bits forem dedicados ao expoente, maior será o intervalo de números que poderá descrever, e quanto mais bits forem dedicados à mantissa, mais números poderá descrever dentro desse intervalo. 

Independentemente do formato FP8 escolhido, não é possível representar 4,543 com precisão. Se optar pelo E4M3, com a sua precisão relativamente superior, poderá obter o resultado mais próximo (4,5). No E5M2, o valor mais próximo que se pode obter é 5.

Por outro lado, apesar dessa falta de alcance e precisão, o FP8 permite um cálculo mais rápido e requer uma memória significativamente reduzida em comparação com o BF16. Isso é extremamente valioso para a inferência e, com a abordagem correta, também pode ser extremamente valioso para acelerar o processo de treinar. A questão é: qual é o nível de alcance e precisão que o treinamento de LLM realmente necessita? É necessário representar a idade da Terra com precisão? Ou chegar a 43 milhões de anos é suficientemente próximo? Se estiver interessado no universo como um todo, provavelmente ficará satisfeito com esse segundo nível de precisão. Afinal, o erro de arredondamento representa apenas cerca de 0,3% da idade do universo.

A jornada da DeepL demonstra que o FP8 é capaz de fornecer o necessário para o treinamento de LLM de alta qualidade, o que abriu novas possibilidades para o que treinamos os nossos modelos a realizar e como os implementamos na prática.

Pré-treinar para LLMs DeepL

A jornada que empreendemos com o treinamento e a inferência FP8 começa com o pré-treinamento dos nossos LLMs. Após o pré-treinamento, treinamos os nossos modelos para determinadas tarefas, destilamos modelos grandes em modelos menores, realizamos aprendizagem por reforço e implementamos as definições de estratégias de paralelização para que possamos utilizar o grande número de GPUs que possuímos.

Aplicando o formato FP8 para treinar precisão mista

Realizamos a transição do nosso código de treinamento existente de BF16 para FP8 utilizando o NVIDIA Transformer Engine: uma biblioteca de treinamento fornecida pela NVIDIA que acelera modelos transformadores e é compatível com FP8. O Transformer Engine fornece componentes essenciais que facilitam o treinar de precisão mista, gerenciando perfeitamente a conversão entre os formatos FP8 e BF16 e lidando com fatores de escala.

Utilizamos a configuração padrão do Transformer Engine, conforme recomendado pela NVIDIA, utilizando E4M3 na passagem direta para treinar e, em seguida, utilizando E5M2 na passagem reversa. Isto significa efetivamente que estamos a utilizar o formato com maior precisão para prever a distribuição de probabilidade do próximo token e, em seguida, o formato com menor precisão, mas com um intervalo maior, para calcular os gradientes necessários para atualizar o modelo, quando a precisão é menos importante. Utilizamos cada um dos dois formatos para a tarefa a que melhor se adequa.

No gráfico abaixo, representámos todos os números que podem ser expressos no formato E4M3. Como poderá observar, esses números estão concentrados em torno de zero, com um valor máximo inferior a 500. De facto, o número de valores representáveis para formatos FP8 pode ser apresentado numa tabela muito curta. O segredo para fazer este formato funcionar para treinar é estar ciente da distribuição desses valores e trabalhar dentro dela. 

Isso envolve armazenar fatores de escala adicionais juntamente com os tensores de peso FP8 para superar o alcance limitado e evitar overflow e underflow. Ao realizar cálculos com os seus tensores de baixa precisão, é necessário considerar também os fatores de escala. Por exemplo, ao multiplicar dois tensores, utiliza-se a fórmula: (A_fp8 * A_scale) x (B_fp8 * B_scale), onde A_fp8 e B_fp8 são tensores de 8 bits e as escalas são escalares de 32 bits. Existem dispositivos de hardware específicos que são compatíveis com estas operações.

FP8 versus BF16 para desempenho de treinar

Quando discutimos o desempenho do treinamento, estamos nos referindo à rapidez com que um modelo pode ser treinado, considerando o poder de computação disponível para ele. Para comparar o desempenho de treinamento entre FP8 e BF16, analisamos a utilização do modelo FLOPS (MFU), que é o número de operações de ponto flutuante por segundo (FLOPS) que o modelo realiza, como uma porcentagem do FLOPS que é tecnicamente possível com o hardware disponível.

Para a nossa comparação, utilizámos o número de FLOPS possíveis com o formato BF16 como denominador comum, apesar do facto de, tecnicamente falando, ser possível obter mais FLOPS ao mudar para FP8. Isso permitiu-nos avaliar o ganho incremental no uso da capacidade de processamento disponível que se torna possível quando se passa de BF16 para FP8.

Conforme demonstrado no gráfico abaixo, a eficiência com que o nosso modelo de treinar utiliza o poder de computação disponível aumentou de 44,6% MFU para 67% MFU com FP8, acelerando efetivamente o nosso modelo de treinar em 50%.

Trata-se de um ganho de desempenho notável, por si só. Para alcançar este objetivo, colaborámos com a NVIDIA para otimizar a utilização das funções do Transformer Engine. Com base em outra configuração de treinar, conseguimos aumentar gradualmente o desempenho do treinar em 25% ao longo de 15 meses, levando-nos a atingir 80% de MFU.

FP8 versus BF16 para a qualidade do treinamento LLM

Os ganhos do FP8 em termos de desempenho de treinar são, portanto, realmente impressionantes. No entanto, o resultado que realmente nos interessa na DeepL é a qualidade de treinar. Como isso se compararia à qualidade de treinar com precisão BF16?

Para verificar a qualidade que o FP8 oferece, testamos de treinar um dos nossos modelos em ambos os formatos. Isso permitiu-nos comparar as perdas de treinamento e a qualidade a jusante. 

Treinámos um modelo de 1,5 mil milhões de tokens em três biliões de tokens e, em seguida, comparámos a qualidade do treino FP8 com o BF16. A medida principal aqui foi a perda de treinar, que se refere à capacidade do modelo de prever o próximo token.

Como pode observar no gráfico abaixo, foi possível detectar uma pequena superioridade do BF16 em relação ao FP8, conforme demonstrado pela nossa linha FP8, que se mantém ligeiramente acima da linha BF16. No entanto, essa diferença é ofuscada pelas flutuações muito maiores na perda de treinar de uma etapa para a outra que ocorrem em ambos os formatos e, em ambos os casos, observamos o mesmo aperfeiçoamento tangível na minimização da perda de treinar ao longo do tempo.

Qualidade do treinamento downstream FP8 vs BF16

Em seguida, passamos a testar a qualidade que o treinamento em FP8 versus BF16 proporcionava em uma aplicação prática a jusante.

Neste caso, testámos o desempenho do modelo ao trabalhar com inglês e alemão. Comparamos a perplexidade de validação, que quantifica a incerteza que um modelo experimenta ao prever o próximo token numa sequência. Mais uma vez, a expectativa é que a perplexidade diminua com o tempo. Neste cenário prático, não observámos qualquer degradação na qualidade ao se treinar com FP8 em comparação com o BF16.

O resultado líquido da mudança de BF16 para FP8 é que conseguimos treinar os nossos modelos mais rapidamente, com menor exigência de memória, e alcançar a mesma qualidade de treino, com apenas uma degradação mínima em termos de perda de treino e perplexidade de validação comparável. Na prática, isso significa que o DeepL é capaz de construir modelos mais sofisticados, lidando com tarefas mais complexas, através da maximização da utilização do poder de processamento. Isso amplia significativamente o escopo do que podemos realizar ao treinar LLM.

De treinar FP8 à inferência

A próxima etapa da jornada envolve a preparação de LLMs para inferência de produção. Aqui, o trabalho pesado de suporte é realizado pelo NVIDIA TensorRT-LLM, que é a solução da NVIDIA para inferência LLM escalável e que é compatível com FP8. Ele obtém os pesos do seu modelo a partir de treinar e constrói um mecanismo para otimizar as operações do modelo, tornando-o o mais eficiente possível em termos de computação, utilizando técnicas de otimização como fusão de kernel, código C++/CUDA otimizado, cache KV e processamento contínuo em lote. 

Os benefícios do FP8 para inferência

A inferência para LLMs envolve sempre a interação entre a taxa de transferência (o número de tokens que podem ser processados num determinado período de tempo) e a latência. É evidente que proporcionar a melhor experiência possível ao cliente envolve o controlo da latência. No entanto, a taxa de transferência também é extremamente importante para a DeepL, pois define o número de solicitações que podemos processar num determinado momento e, portanto, o escopo do que o nosso modelo pode realizar na prática.

É inevitável que, à medida que a taxa de transferência aumenta, a latência também tenda a aumentar. Agrupar várias solicitações permite um maior rendimento, mas ao custo de um aumento da latência para cada solicitação individual. Isso pode afetar a experiência do cliente. No entanto, o desempenho de inferência do FP8 em comparação com o BF16 altera significativamente esse equilíbrio a nosso favor.

Conforme ilustrado no gráfico abaixo, para a maioria dos tamanhos de lote, o FP8 pode processar o dobro da taxa de transferência com o mesmo grau de latência que o BF16. Se definirmos um orçamento de latência específico que corresponda à experiência ideal para os nossos utilizadores, poderemos observar isso na prática. Na prática, o FP8 duplicou efetivamente a capacidade efetiva dos nossos LLMs em termos de rendimento. 

Em outras palavras, a transição do BF16 para o FP8 não apenas nos permitiu desenvolver LLMs mais potentes e sofisticados para o DeepL. Isso também garante que possamos aplicar esses LLMs de forma eficaz, para oferecer experiências ideais aos clientes e ampliar o impacto da nossa IA linguística no mundo real. Conseguimos treinar mais rápido modelos maiores, que podem então operar dentro dos mesmos parâmetros de latência, enquanto processam o dobro do número de solicitações.

Qual é o próximo passo? Recentemente, implementámos o novo NVIDIA DGX SuperPOD com sistemas NVIDIA DGX GB200, que proporciona outro aumento quase exponencial na capacidade de computação. O que é realmente interessante para nós é que esta máquina introduzirá uma nova geração de Tensor Cores que poderão ser compatíveis com nativamente operações tensoriais FP4, como multiplicações matriciais. É nesse momento que a nossa jornada recomeça. Tem sido emocionante observar o que podemos realizar com um único byte quando se trata de treinar e de inferência. Acompanhe este espaço para descobrir o que é possível fazer com meio byte.


Sobre os autores

Markus Schnös, Engenheiro de Investigação HPC

Markus Schnös é engenheiro de pesquisa HPC na DeepL, onde se concentra em dimensionar o treinamento e a inferência de LLM. Ele tem um interesse especial no treinamento distribuído e na computação de ponto flutuante de baixa precisão.

www.linkedin.com/in/markus-schnoes-349300185

https://github.com/Marks101

Fabian Joswig, Engenheiro de Investigação HPC

Fabian Joswig é engenheiro de investigação na DeepL, com experiência em aprendizagem automática, computação de alto desempenho e física teórica de partículas. Ele concentra-se em dimensionar modelos e infraestruturas de IA para o tradutor mais preciso do mundo.

https://www.linkedin.com/in/fabianjoswig/

https://github.com/fjosw

Partilhar