Você está em uma entrevista para Engenheiro de ML no Google. Entrevistador: Precisamos treinar um LLM em 1.000 GPUs. Como você garantiria que todas as GPUs compartilhem o que aprendem? Você: Use um servidor de parâmetros central para agregar e redistribuir os pesos. Entrevista encerrada. Aqui está o que você perdeu:
Um grande gargalo de tempo de execução no treinamento multi-GPU ocorre durante a sincronização das GPUs. Por exemplo, no treinamento multi-GPU através do paralelismo de dados: - O mesmo modelo é distribuído para diferentes GPUs. - Cada GPU processa um subconjunto diferente de todo o conjunto de dados. Verifique isto 👇
Isto leva a diferentes gradientes em diferentes dispositivos. Portanto, antes de atualizar os parâmetros do modelo em cada dispositivo GPU, devemos comunicar os gradientes a todos os outros dispositivos para sincronizá-los. Vamos entender 2 estratégias comuns a seguir!
Algoritmo 1) All-reduce Uma maneira óbvia é enviar os gradientes de um dispositivo para todos os outros dispositivos para sincronizá-los. Mas isso utiliza uma largura de banda alta. Se cada GPU tem “N” elementos e há “G” GPUs, resulta em uma transferência total de G*(G-1)*N elementos 👇
Podemos otimizar isso transferindo todos os elementos para uma única GPU, calculando o valor final e enviando-o de volta para todas as outras GPUs. Isto é uma melhoria significativa. Mas agora uma única GPU deve receber, calcular e comunicar de volta os gradientes, portanto, isso não escala.
Algoritmo 2) Redução em anel Fase #1) Redução de compartilhamento Primeiro, os gradientes são divididos em G segmentos em cada GPU (G = número total de GPUs). Verifique isto 👇
Numa iteração, cada GPU envia um segmento para a próxima GPU: - GPU1 envia a₁ para GPU2, onde é adicionado a b₁ - GPU2 envia b₂ para GPU3, onde é adicionado a c₂ - GPU3 envia c₃ para GPU4, onde é adicionado a d₃ - GPU4 envia d₄ para GPU1, onde é adicionado a a₄ Verifique isto 👇
Este processo é feito novamente: - GPU1 envia (d₄+a₄) para GPU2, onde é adicionado a b₄. - GPU2 envia (a₁+b₁) para GPU3, onde é adicionado a c₁. - GPU3 envia (b₂+c₂) para GPU4, onde é adicionado a d₂. - GPU4 envia (c₃+d₃) para GPU1, onde é adicionado a a₃. Verifique isto 👇
Na iteração final, os seguintes segmentos são transferidos para a próxima GPU. Isto leva a um estado onde cada GPU tem um segmento inteiro, e podemos transferir esses segmentos completos para todas as outras GPUs. Verifique isto 👇
Fase #2) Apenas compartilhar Agora que cada GPU tem um segmento inteiro, podemos transferir esses segmentos completos para todas as outras GPUs. O processo é realizado de forma semelhante ao que discutimos acima, por isso não entraremos em detalhes completos. A iteração 1 é mostrada abaixo👇
Em seguida, realizamos as iterações 2 e 3. Estas são realizadas de forma semelhante ao que aprendemos na Fase 1. Verifique isto 👇
E aí está! Os pesos do modelo foram sincronizados entre as GPUs. Embora o total de elementos transferidos continue o mesmo que tínhamos na abordagem "single-GPU-master", esta abordagem em anel é muito mais escalável, pois não coloca toda a carga em uma única GPU. Verifique isto 👇
Por defeito, os modelos de deep learning utilizam apenas uma única GPU para treino, mesmo que várias GPUs estejam disponíveis. Uma forma ideal de treinar modelos é distribuir a carga de trabalho de treino por várias GPUs. O gráfico ilustra quatro estratégias para treino em múltiplas GPUs👇
364,83K