Vista geral do Cloud TPU Multislice
posteriores da TPU.O Cloud TPU Multislice é uma tecnologia de escalamento de desempenho de pilha completa que permite que uma tarefa de preparação use várias divisões de TPU numa única divisão ou em divisões em vários Pods com paralelismo de dados padrão. Com os chips TPU v4, isto significa que as tarefas de preparação podem usar mais de 4096 chips numa única execução. Para tarefas de preparação que requerem menos de 4096 chips, uma única fatia pode oferecer o melhor desempenho. No entanto, estão mais facilmente disponíveis várias divisões mais pequenas, o que permite um tempo de início mais rápido quando a funcionalidade de várias divisões é usada com divisões mais pequenas.
Quando implementados em configurações de várias fatias, os chips de TPU em cada fatia comunicam através da interligação entre chips (ICI). Os chips de TPU em diferentes fatias comunicam transferindo dados para CPUs (anfitriões), que, por sua vez, transmitem os dados através da rede do centro de dados (DCN). Para mais informações sobre a escalabilidade com o Multislice, consulte o artigo Como dimensionar a preparação de IA para até dezenas de milhares de chips Cloud TPU com o Multislice.
Os programadores não têm de escrever código para implementar a comunicação DCN entre segmentos. O compilador XLA gera esse código por si e sobrepõe a comunicação com os cálculos para um desempenho máximo.
Conceitos
- Tipo de acelerador
- O formato de cada slice de TPU
que compõe um Multislice. Cada fatia num pedido de várias fatias é do mesmo tipo de acelerador. Um tipo de acelerador
consiste num tipo de TPU (v4 ou posterior) seguido do número de TensorCores.
Por exemplo,
v5litepod-128
especifica uma TPU v5e com 128 TensorCores. - Reparação automática
- Quando uma divisão encontra um evento de manutenção, uma preempção ou uma falha de hardware, o Cloud TPU cria uma nova divisão. Se existirem recursos insuficientes para criar uma nova fatia, a criação não é concluída até que o hardware fique disponível. Depois de criar a nova fatia, todas as outras fatias no ambiente Multislice são reiniciadas para que a preparação possa continuar. Com um script de início configurado corretamente, o script de preparação pode ser reiniciado automaticamente sem intervenção do utilizador, carregando e retomando a partir do ponto de verificação mais recente.
- Redes de centros de dados (DCN)
- Uma rede com latência mais elevada e débito mais baixo (quando comparada com a ICI) que liga fatias de TPU numa configuração de várias fatias.
- Agendamento em grupo
- Quando todas as divisões de TPU são aprovisionadas em conjunto, ao mesmo tempo, garantindo que todas ou nenhuma das divisões são aprovisionadas com êxito.
- Interligação entre chips (ICI)
- Ligações internas de alta velocidade e baixa latência que ligam TPUs num TPU Pod.
- Multislice
- Duas ou mais divisões do chip da TPU que podem comunicar através da DCN.
- Node
- No contexto de Multislice, o nó refere-se a uma única divisão da TPU. Cada fatia de TPU num Multislice recebe um ID do nó.
- Script de arranque
- Um script de arranque do Compute Engine padrão que é executado sempre que uma VM é iniciada ou reiniciada. Para o Multislice, é especificado no pedido de criação de QR. Para mais informações sobre scripts de arranque do Cloud TPU, consulte o artigo Gerir recursos de TPU.
- Tensor
- Uma estrutura de dados usada para representar dados multidimensionais num modelo de aprendizagem automática.
- Tipos de capacidade do Cloud TPU
As TPUs podem ser criadas a partir de diferentes tipos de capacidade (consulte as opções de utilização em Como funciona o preço das TPUs):
Reserva: para consumir uma reserva, tem de ter um contrato de reserva com a Google. Use a flag
--reserved
quando criar os seus recursos.Spot: segmenta a quota preemptiva com VMs do Spot. Os seus recursos podem ser interrompidos para dar lugar a pedidos de uma tarefa de prioridade mais elevada. Use a flag
--spot
ao criar os seus recursos.A pedido: segmenta a quota a pedido, que não precisa de reserva e não é antecipada. O pedido de TPU é colocado numa fila de quotas a pedido oferecida pela Cloud TPU. A disponibilidade de recursos não é garantida. Selecionado por predefinição, não são necessárias etiquetas.
Começar
Configure o seu ambiente de Cloud TPU.
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
ici_data_parallelism
ici_fsdp_parallelism
ici_tensor_parallelism
Configure o ambiente:
$ gcloud auth login $ export QR_ID=your-queued-resource-id $ export TPU_NAME=your-tpu-name $ export PROJECT=your-project-name $ export ZONE=us-central1-a $ export NETWORK_NAME=your-network-name $ export SUBNETWORK_NAME=your-subnetwork-name $ export RUNTIME_VERSION=v2-alpha-tpuv5-lite $ export ACCELERATOR_TYPE=v5litepod-16 $ export EXAMPLE_TAG_1=your-tag-1 $ export EXAMPLE_TAG_2=your-tag-2 $ export SLICE_COUNT=4 $ export STARTUP_SCRIPT='#!/bin/bash\n'
Descrições de variáveis
Entrada Descrição QR_ID O ID atribuído pelo utilizador do recurso em fila. TPU_NAME O nome atribuído pelo utilizador da sua TPU. PROJECT Google Cloud nome do projeto ZONE Especifica a zona na qual criar os recursos. NETWORK_NAME Nome das redes VPC. SUBNETWORK_NAME Nome da sub-rede nas redes VPC RUNTIME_VERSION A versão do software do Cloud TPU. ACCELERATOR_TYPE v4-16 EXAMPLE_TAG_1, EXAMPLE_TAG_2 … Etiquetas usadas para identificar origens ou destinos válidos para firewalls de rede SLICE_COUNT Número de fatias. Limitado a um máximo de 256 fatias. STARTUP_SCRIPT Se especificar um script de arranque, o script é executado quando a fatia de TPU é aprovisionada ou reiniciada. Crie chaves SSH para
gcloud
. Recomendamos que deixe uma palavra-passe em branco (prima Enter duas vezes depois de executar o seguinte comando). Se lhe for pedido que o ficheirogoogle_compute_engine
já existe, substitua a versão existente.$ ssh-keygen -f ~/.ssh/google_compute_engine
Aprovisione as suas TPUs:
gcloud
$ gcloud compute tpus queued-resources \ create ${QR_ID} \ --accelerator-type=${ACCELERATOR_TYPE} \ --runtime-version=${RUNTIME_VERSION} \ --node-id=${TPU_NAME} \ --zone=${ZONE} \ [--reserved |--spot]
A CLI Google Cloud não suporta todas as opções de criação de QR, como etiquetas. Para mais informações, consulte Crie QRs.
Consola
Na Google Cloud consola, aceda à página TPUs:
Clique em Criar TPU.
No campo Nome, introduza um nome para a TPU.
Na caixa Zona, selecione a zona onde quer criar a TPU.
Na caixa Tipo de TPU, selecione um tipo de acelerador. O tipo de acelerador especifica a versão e o tamanho da Cloud TPU que quer criar. Para mais informações sobre os tipos de aceleradores suportados para cada versão da TPU, consulte o artigo Versões da TPU.
Na caixa Versão do software da TPU, selecione uma versão do software. Quando cria uma VM do Cloud TPU, a versão do software da TPU especifica a versão do tempo de execução da TPU a instalar. Para mais informações, consulte o artigo Versões de software da TPU.
Clique no botão de ativar/desativar Ativar colocação em fila.
No campo Nome do recurso em fila, introduza um nome para o seu pedido de recurso em fila.
Clique em Criar para criar o pedido de recursos em fila.
Aguarde até que o recurso em fila esteja no estado
ACTIVE
, o que significa que os nós de trabalho estão no estadoREADY
. Assim que o aprovisionamento de recursos em fila de espera for iniciado, pode demorar entre 1 e 5 minutos a ser concluído, consoante o tamanho do recurso em fila de espera. Pode verificar o estado de um pedido de recurso em fila de espera através da CLI gcloud ou da Google Cloud consola:gcloud
$ gcloud compute tpus queued-resources \ list --filter=${QR_ID} --zone=${ZONE}
Consola
Na Google Cloud consola, aceda à página TPUs:
Clique no separador Recursos em fila.
Clique no nome do seu pedido de recurso em fila.
Estabeleça ligação à VM de TPU através de SSH:
$ gcloud compute tpus tpu-vm ssh ${TPU_NAME} --zone=${ZONE}
Clone o MaxText (que inclui o
shardings.py
) para a sua VM da TPU:$ git clone https://github.com/AI-Hypercomputer/maxtext && cd maxtext
Instale o Python 3.10:
$ sudo apt-get update $ sudo apt install python3.10 $ sudo apt install python3.10-venv
Crie e ative um ambiente virtual:
$ python3 -m venv your-venv-name $ source your-venv-name/bin/activate
No diretório do repositório MaxText, execute o script de configuração para instalar o JAX e outras dependências na sua fatia de TPU. O script de configuração demora alguns minutos a ser executado.
$ bash setup.sh
Execute o seguinte comando para executar o
shardings.py
na sua fatia de TPU.$ python3 -m pedagogical_examples.shardings \ --ici_fsdp_parallelism 4 \ --batch_size 131072 \ --embedding_dimension 2048
Pode ver os resultados nos registos. As suas UTPs devem atingir cerca de 260 TFLOPs por segundo ou uma utilização de FLOPs impressionante de mais de 90%! Neste caso, selecionámos aproximadamente o lote máximo que se ajusta à memória de largura de banda elevada (HBM) da TPU.
Não hesite em explorar outras estratégias de divisão na ICI. Por exemplo, pode experimentar a seguinte combinação:
$ python3 -m pedagogical_examples.shardings \ --ici_tensor_parallelism 4 \ --batch_size 131072 \ --embedding_dimension 2048
Elimine o recurso em fila e a fatia de TPU quando terminar. Deve executar estes passos de limpeza no ambiente onde configurou a fatia (primeiro, execute
exit
para sair da sessão de SSH). A eliminação demora entre dois e cinco minutos. Se estiver a usar a CLI gcloud, pode executar este comando em segundo plano com a flag--async
opcional.gcloud
$ gcloud compute tpus queued-resources \ delete ${QR_ID} --force (--async)
Consola
Na Google Cloud consola, aceda à página TPUs:
Clique no separador Recursos em fila.
Selecione a caixa de verificação junto ao pedido de recurso em fila.
Clique em
Eliminar.
- dcn_data_parallelism
- dcn_fsdp_parallelism
- dcn_tensor_parallelism
Clone o MaxText na máquina do executor:
$ git clone https://github.com/AI-Hypercomputer/maxtext
Aceda ao diretório do repositório.
$ cd maxtext
Para criar chaves SSH para
gcloud
, recomendamos que deixe uma palavra-passe em branco (prima Enter duas vezes depois de executar o seguinte comando). Se lhe for pedido que o ficheirogoogle_compute_engine
já existe, selecione a opção para não manter a sua versão existente.$ ssh-keygen -f ~/.ssh/google_compute_engine
Adicione uma variável de ambiente para definir a contagem de fatias de TPU como
2
.$ export SLICE_COUNT=2
Crie um ambiente de várias divisões com o comando
queued-resources create
ou a consola Google Cloud .gcloud
O comando seguinte mostra como criar uma TPU Multislice v5e. Para usar uma versão diferente da TPU, especifique um
accelerator-type
diferente eruntime-version
.$ gcloud compute tpus queued-resources \ create ${QR_ID} \ --accelerator-type=${ACCELERATOR_TYPE} \ --runtime-version=${RUNTIME_VERSION} \ --node-count=${SLICE_COUNT} \ --node-prefix=${TPU_NAME} \ --zone=${ZONE} \ [--reserved|--spot]
Consola
Na Google Cloud consola, aceda à página TPUs:
Clique em Criar TPU.
No campo Nome, introduza um nome para a TPU.
Na caixa Zona, selecione a zona onde quer criar a TPU.
Na caixa Tipo de TPU, selecione um tipo de acelerador. O tipo de acelerador especifica a versão e o tamanho da Cloud TPU que quer criar. O multislice só é suportado na TPU Cloud v4 e em versões posteriores da TPU. Para mais informações sobre as versões de TPU, consulte o artigo Versões de TPU.
Na caixa Versão do software da TPU, selecione uma versão do software. Quando cria uma VM do Cloud TPU, a versão do software da TPU especifica a versão do tempo de execução da TPU a instalar nas VMs da TPU. Para mais informações, consulte o artigo Versões de software da TPU.
Clique no botão de ativar/desativar Ativar colocação em fila.
No campo Nome do recurso em fila, introduza um nome para o seu pedido de recurso em fila.
Clique na caixa de verificação Make this a Multislice TPU (Transformar isto num TPU de vários segmentos).
No campo Número de divisões, introduza o número de divisões que quer criar.
Clique em Criar para criar o pedido de recursos em fila.
Quando o aprovisionamento de recursos em fila começa, pode demorar até cinco minutos a ser concluído, consoante o tamanho do recurso em fila. Aguarde até que o recurso em fila esteja no estado
ACTIVE
. Pode verificar o estado de um pedido de recurso em fila de espera através da CLI gcloud ou da Google Cloud consola:gcloud
$ gcloud compute tpus queued-resources list \ --filter=${QR_ID} --zone=${ZONE} --project=${PROJECT}
Isto deve gerar um resultado com o seguinte aspeto:
NAME ZONE NODE_COUNT ACCELERATOR_TYPE STATE ... que-res-id us-central2-b 4 v5litepod-16 ACTIVE ...
Consola
Na Google Cloud consola, aceda à página TPUs:
Clique no separador Recursos em fila.
Clique no nome do seu pedido de recurso em fila.
Contacte o seu Google Cloud representante da conta se o estado do QR estiver no estado
WAITING_FOR_RESOURCES
ouPROVISIONING
durante mais de 15 minutos.Instale dependências.
$ python3 multihost_runner.py \ --TPU_PREFIX=${TPU_NAME} \ --ZONE=${ZONE} \ --COMMAND="bash setup.sh"
Execute
shardings.py
em cada trabalhador através domultihost_runner.py
.$ python3 multihost_runner.py \ --TPU_PREFIX=${TPU_NAME} \ --ZONE=${ZONE} \ --COMMAND="python3 -m pedagogical_examples.shardings \ --dcn_data_parallelism ${SLICE_COUNT} \ --ici_fsdp_parallelism 16 \ --batch_size 131072 \ --embedding_dimension 2048"
Vai ver aproximadamente 230 TFLOPs por segundo de desempenho nos ficheiros de registo.
Para mais informações sobre a configuração do paralelismo, consulte os artigos Fragmentação em vários segmentos com paralelismo da DCN e
shardings.py
.Limpe as UTPs e os recursos em fila quando terminar. A eliminação demora entre dois e cinco minutos. Se estiver a usar a CLI gcloud, pode executar este comando em segundo plano com a flag
--async
opcional.- Use jax.experimental.mesh_utils.create_hybrid_device_mesh em vez de jax.experimental.mesh_utils.create_device_mesh quando criar a sua malha.
- Usando o script do executor de experiências,
multihost_runner.py
- Usando o script do executor de produção,
multihost_job.py
- Usar uma abordagem manual
Crie um pedido de recursos em fila usando o seguinte comando:
$ gcloud compute tpus queued-resources \ create ${QR_ID} \ --project=${PROJECT} \ --zone=${ZONE} \ --node-count=${SLICE_COUNT} \ --accelerator-type=${ACCELERATOR_TYPE} \ --runtime-version=${RUNTIME_VERSION} \ --network=${NETWORK_NAME} \ --subnetwork=${SUBNETWORK_NAME} \ --tags=${EXAMPLE_TAG_1},${EXAMPLE_TAG_2} \ --metadata=startup-script="${STARTUP_SCRIPT}" \ [--reserved|--spot]
Crie um ficheiro denominado
queued-resource-req.json
e copie o seguinte JSON para o mesmo.{ "guaranteed": { "reserved": true }, "tpu": { "node_spec": [ { "parent": "projects/your-project-number/locations/your-zone", "node": { "accelerator_type": "accelerator-type", "runtime_version": "tpu-vm-runtime-version", "network_config": { "network": "your-network-name", "subnetwork": "your-subnetwork-name", "enable_external_ips": true }, "tags" : ["example-tag-1"] "metadata": { "startup-script": "your-startup-script" } }, "multi_node_params": { "node_count": slice-count, "node_id_prefix": "your-queued-resource-id" } } ] } }
Substitua os seguintes valores:
- your-project-number - O seu Google Cloud número do projeto
- your-zone - A zona na qual quer criar o recurso em fila
- accelerator-type - A versão e o tamanho de uma única fatia. O Multislice só é suportado na Cloud TPU v4 e em versões posteriores da TPU.
- tpu-vm-runtime-version: a versão de tempo de execução da VM da TPU que quer usar.
- your-network-name - Opcional, uma rede à qual o recurso em fila vai ser anexado
- your-subnetwork-name - Opcional, uma sub-rede à qual o recurso em fila vai ser anexado
- example-tag-1: opcional, uma string de etiqueta arbitrária
- your-startup-script: um script de arranque que é executado quando o recurso em fila é atribuído
- slice-count: o número de fatias de TPU no seu ambiente de várias fatias
- your-queued-resource-id - O ID fornecido pelo utilizador para o recurso em fila
Para mais informações, consulte a documentação da API REST de recursos em fila para ver todas as opções disponíveis.
Para usar a capacidade de spot, substitua:
"guaranteed": { "reserved": true }
com"spot": {}
Remova a linha para usar a capacidade a pedido predefinida.
Envie o pedido de criação de recursos em fila com o payload JSON:
$ curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json" \ -d @queuedresourcereq.json \ https://tpu.googleapis.com/v2alpha1/projects/your-project-id/locations/your-zone/queuedResources\?queued_resource_id\=your-queued-resource-id
Substitua os seguintes valores:
- your-project-id - O ID do seu Google Cloud projeto
- your-zone - A zona na qual quer criar o recurso em fila
- your-queued-resource-id - O ID fornecido pelo utilizador para o recurso em fila
Na Google Cloud consola, aceda à página TPUs:
Clique em Criar TPU.
No campo Nome, introduza um nome para a TPU.
Na caixa Zona, selecione a zona onde quer criar a TPU.
Na caixa Tipo de TPU, selecione um tipo de acelerador. O tipo de acelerador especifica a versão e o tamanho da Cloud TPU que quer criar. O Multislice só é suportado na Cloud TPU v4 e em versões posteriores da TPU. Para mais informações sobre os tipos de aceleradores suportados para cada versão da TPU, consulte o artigo Versões da TPU.
Na caixa Versão do software da TPU, selecione uma versão do software. Quando cria uma VM do Cloud TPU, a versão do software da TPU especifica a versão do tempo de execução da TPU a instalar. Para mais informações, consulte o artigo Versões de software da TPU.
Clique no botão de ativar/desativar Ativar colocação em fila.
No campo Nome do recurso em fila, introduza um nome para o seu pedido de recurso em fila.
Clique na caixa de verificação Make this a Multislice TPU (Transformar isto num TPU de vários segmentos).
No campo Número de divisões, introduza o número de divisões que quer criar.
Clique em Criar para criar o pedido de recursos em fila.
Na Google Cloud consola, aceda à página TPUs:
Clique no separador Recursos em fila.
Clique no nome do seu pedido de recurso em fila.
Na Google Cloud consola, aceda à página TPUs:
Clique no separador Recursos em fila.
Na Google Cloud consola, aceda à página TPUs:
Clique no separador Recursos em fila.
Selecione a caixa de verificação junto ao pedido de recurso em fila.
Clique em
Eliminar.- B é o tamanho do lote em tokens
- P é o número de parâmetros
- Incorre na "bolha de pipeline", em que os chips estão inativos porque estão à espera de dados.
- Requer micro-lotes, o que diminui o tamanho do lote efetivo, a intensidade aritmética e, em última análise, a utilização de FLOPs do modelo.
Para usar o Multislice, os seus recursos de TPU têm de ser geridos como recursos em fila.
Exemplo introdutório
Este tutorial usa código do repositório do GitHub do MaxText. O MaxText é um LLM básico de código aberto, arbitrariamente escalável, de elevado desempenho e bem testado, escrito em Python e Jax. O MaxText foi concebido para ser treinado de forma eficiente na TPU na nuvem.
O código em shardings.py
foi concebido para ajudar a começar a experimentar diferentes opções de paralelismo. Por exemplo, paralelismo de dados, paralelismo de dados totalmente fragmentados (FSDP) e paralelismo de tensores. O código é dimensionado de ambientes de fatia única para vários ambientes de fatias.
Paralelismo de ICI
ICI refere-se à interligação de alta velocidade que liga as TPUs numa única fatia. A divisão em partições de ICI corresponde à divisão em partições numa fatia. shardings.py
oferece três parâmetros de paralelismo da ICI:
Os valores especificados para estes parâmetros determinam o número de fragmentos para cada método de paralelismo.
Estas entradas têm de ser restritas para que ici_data_parallelism * ici_fsdp_parallelism * ici_tensor_parallelism
seja igual ao número de chips na fatia.
A tabela seguinte mostra exemplos de entradas do utilizador para o paralelismo da ICI para os quatro chips disponíveis na v4-8:
ici_data_parallelism | ici_fsdp_parallelism | ici_tensor_parallelism | |
FSDP de 4 vias | 1 | 4 | 1 |
Paralelismo de tensores quadridirecional | 1 | 1 | 4 |
FSDP bidirecional + paralelismo do Tensor bidirecional | 1 | 2 | 2 |
Tenha em atenção que ici_data_parallelism
deve ser deixado como 1 na maioria dos casos, porque a rede ICI é suficientemente rápida para quase sempre preferir o FSDP ao paralelismo de dados.
Este exemplo parte do princípio de que está familiarizado com a execução de código numa única fatia de TPU, como em Executar um cálculo numa VM de TPU na nuvem com o JAX.
Este exemplo mostra como executar shardings.py
numa única fatia.
Particionamento em vários fragmentos com paralelismo de DCN
O script shardings.py
usa três parâmetros que especificam o paralelismo da DCN, correspondente ao número de fragmentos de cada tipo de paralelismo de dados:
Os valores destes parâmetros têm de ser restritos para que dcn_data_parallelism * dcn_fsdp_parallelism * dcn_tensor_parallelism
seja igual ao número de fatias.
Como exemplo para duas fatias, use --dcn_data_parallelism = 2
.
dcn_data_parallelism | dcn_fsdp_parallelism | dcn_tensor_parallelism | N.º de fatias | |
Paralelismo de dados bidirecional | 2 | 1 | 1 | 2 |
dcn_tensor_parallelism
deve ser sempre definido como 1
porque a DCN não é adequada para essa divisão. Para cargas de trabalho típicas de LLM em chips v4, dcn_fsdp_parallelism
também deve ser definido como 1
e, por conseguinte, dcn_data_parallelism
deve ser definido como o número de fatias, mas isto depende da aplicação.
À medida que aumenta o número de divisões (partindo do princípio de que mantém o tamanho da divisão e o lote por divisão constantes), aumenta a quantidade de paralelismo de dados.
Executar o shardings.py
num ambiente de várias divisões
Pode executar shardings.py
num ambiente de vários fragmentos usando multihost_runner.py
ou executando shardings.py
em cada VM de TPU. Aqui, usamos
multihost_runner.py
. Os passos seguintes são muito semelhantes aos descritos no artigo
Introdução: experiências rápidas em várias divisões
do repositório MaxText, exceto que aqui executamos shardings.py
em vez do
LLM mais complexo em train.py
.
A ferramenta multihost_runner.py
está otimizada para experiências rápidas, reutilizando repetidamente as mesmas TPUs. Uma vez que o script multihost_runner.py
depende de ligações SSH de longa duração, não o recomendamos para tarefas de longa duração.
Se quiser executar uma tarefa mais longa (por exemplo, durante horas ou dias), recomendamos que use o comando
multihost_job.py
.
Neste tutorial, usamos o termo runner para indicar a máquina na qual
executa o script multihost_runner.py
. Usamos o termo trabalhadores para indicar as VMs de TPU que compõem as suas divisões. Pode executar o multihost_runner.py
numa máquina local ou em qualquer VM do Compute Engine no mesmo projeto que as suas fatias. A execução de multihost_runner.py
num trabalhador não é suportada.
O multihost_runner.py
liga-se automaticamente aos trabalhadores da TPU através de SSH.
Neste exemplo, executa shardings.py
em duas fatias v5e-16, um total de quatro VMs e 16 chips de TPU. Pode modificar o exemplo para ser executado em mais TPUs.
Configure o seu ambiente
Escalar uma carga de trabalho para o Multislice
Antes de executar o modelo num ambiente de vários segmentos, faça as seguintes alterações ao código:
Estas devem ser as únicas alterações de código necessárias quando se muda para o Multislice. Para alcançar um elevado desempenho, a DCN tem de ser mapeada em eixos paralelos de dados, paralelos de dados totalmente fragmentados ou paralelos de pipeline. As considerações de desempenho e as estratégias de divisão são abordadas mais detalhadamente no artigo Divisão com várias fatias para máximo desempenho.
Para validar que o seu código pode aceder a todos os dispositivos, pode afirmar que
len(jax.devices())
é igual ao número de chips no seu ambiente Multislice. Por exemplo, se estiver a usar quatro fatias de v4-16
, tem oito chips por fatia * 4 fatias, pelo que len(jax.devices())
deve devolver 32.
Escolher os tamanhos das divisões para ambientes com várias divisões
Para obter um aumento linear da velocidade, adicione novas divisões do mesmo tamanho que a divisão existente. Por exemplo, se usar uma fatia v4-512
, o Multislice alcança aproximadamente o dobro do desempenho adicionando uma segunda fatia v4-512
e duplicando o tamanho do lote global. Para mais informações, consulte o artigo
Partição com várias fatias para máximo desempenho.
Executar o seu trabalho em várias divisões
Existem três abordagens diferentes para executar a sua carga de trabalho personalizada num ambiente de vários segmentos:
Script do executor de experiências
O script multihost_runner.py
distribui código a um ambiente Multislice existente e executa
o seu comando em cada anfitrião, copia os seus registos e acompanha o estado de erro de cada comando. O script multihost_runner.py
está documentado no
MaxText README.
Uma vez que o multihost_runner.py
mantém ligações SSH persistentes, só é adequado para experiências de tamanho modesto e duração relativamente curta. Pode
adaptar os passos no multihost_runner.py
tutorial
à sua carga de trabalho e configuração de hardware.
Script do executor de produção
Para tarefas de produção que precisam de resiliência contra falhas de hardware e outras
interrupções, é melhor integrar diretamente com a API Create Queued Resource
(criar recurso em fila). Use multihost_job.py
como exemplo funcional que aciona a chamada da API de recursos em fila com o script de arranque adequado para executar o seu treino e retomá-lo em caso de preemptção. O script está documentado no multihost_job.py
MaxText README.
Uma vez que o multihost_job.py
tem de aprovisionar recursos para cada execução, não oferece um ciclo de iteração tão rápido quanto o multihost_runner.py
.
Abordagem manual
Recomendamos que use ou adapte multihost_runner.py ou multihost_job.py para executar a sua carga de trabalho personalizada na configuração de várias fatias. No entanto, se preferir aprovisionar e gerir o seu ambiente através de comandos QR diretamente, consulte o artigo Gerir um ambiente com várias divisões.
Faça a gestão de um ambiente Multislice
Para aprovisionar e gerir manualmente QRs sem usar as ferramentas disponibilizadas no repositório MaxText, leia as secções seguintes.
Crie recursos em fila
gcloud
Certifique-se de que tem a quota respetiva antes de selecionar --reserved
,
--spot
ou a quota a pedido predefinida. Para obter informações sobre os tipos de quotas,
consulte a Política de Quotas.
curl
A resposta deve ter o seguinte aspeto:
{ "name": "projects/<your-project-id>/locations/<your-zone>/operations/operation-<your-qr-guid>", "metadata": { "@type": "type.googleapis.com/google.cloud.common.OperationMetadata", "createTime": "2023-11-01T00:17:05.742546311Z", "target": "projects/<your-project-id>/locations/<your-zone>/queuedResources/<your-qa-id>", "verb": "create", "cancelRequested": false, "apiVersion": "v2alpha1" }, "done": false }
Use o valor GUID no final do valor da string do atributo name
para obter informações sobre o pedido de recurso em fila.
Consola
Obtenha o estado de um recurso em fila
gcloud
$ gcloud compute tpus queued-resources describe ${QR_ID} --zone=${ZONE}
Para um recurso em fila que se encontra no estado ACTIVE
, o resultado tem o seguinte aspeto:
... state: state: ACTIVE ...
curl
$ curl -X GET -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json" https://tpu.googleapis.com/v2/projects/your-project-id/locations/your-zone/queuedResources/${YOUR_QR_ID}
Para um recurso em fila que se encontra no estado ACTIVE
, o resultado tem o seguinte aspeto:
{ "name": your-queued-res, "tpu": { "nodeSpec": [ { ... // node 1 }, { ... // node 2 }, ... ] }, ... "state": "ACTIVE" }
Consola
Depois de o TPU ter sido aprovisionado, também pode ver detalhes sobre o pedido de recursos em fila de espera acedendo à página TPUs, encontrando o seu TPU e clicando no nome do pedido de recursos em fila de espera correspondente.
Num cenário raro, pode encontrar o recurso em fila no estado FAILED
enquanto algumas fatias estão ACTIVE
. Se isto acontecer, elimine os recursos criados e tente novamente dentro de alguns minutos ou contacte o Google Cloud apoio técnico.
SSH e instalar dependências
Execute código JAX em fatias de TPU
descreve como estabelecer ligação às suas VMs de TPU através de SSH numa única fatia. Para
estabelecer ligação a todas as VMs de TPU no seu ambiente de vários fragmentos através de SSH e
instalar dependências, use o seguinte comando gcloud
:
$ gcloud compute tpus queued-resources ssh ${QR_ID} \ --zone=${ZONE} \ --node=all \ --worker=all \ --command="command-to-run" \ --batch-size=4
Este comando gcloud
envia o comando especificado a todos os trabalhadores e nós no QR através de SSH. O comando é processado em lotes de quatro e enviado
em simultâneo. O lote de comandos seguinte é enviado quando o lote atual
conclui a execução. Se ocorrer uma falha com um dos comandos, o processamento é interrompido e não são enviados mais lotes. Para mais informações, consulte a
referência da API de recursos em fila.
Se o número de divisões que está a usar exceder o limite de processamento simultâneo do seu computador local (também denominado limite de processamento em lote), vai deparar-se com um impasse. Por exemplo, suponha que o limite de processamento em lote na sua máquina local é 64. Se tentar executar um script de
preparação em mais de 64 fatias, por exemplo, 100, o comando SSH divide
as fatias em lotes. Executa o script de preparação no primeiro lote de 64 fatias e aguarda a conclusão dos scripts antes de executar o script no lote restante de 36 fatias. No entanto, o primeiro lote de 64 fatias não pode ser concluído até que as 36 fatias restantes comecem a executar o script, o que causa um impasse.
Para evitar este cenário, pode executar o script de preparação em segundo plano em cada VM anexando um e comercial (&
) ao comando do script que especificar com a sinalização --command
. Quando o faz, depois de iniciar o script de preparação
no primeiro lote de fatias, o controlo é imediatamente devolvido
ao comando SSH. O comando SSH pode, então, começar a executar o script de preparação no lote restante de 36 fatias. Tem de encaminhar os streams stdout
e stderr
adequadamente quando executar os comandos em segundo plano. Para aumentar o paralelismo no mesmo QR, pode selecionar fatias específicas através do parâmetro --node
.
Configuração de rede
Certifique-se de que as fatias de TPU conseguem comunicar entre si seguindo os passos abaixo.
Instale o JAX em cada uma das divisões. Para mais informações, consulte o artigo
Execute código JAX em fatias de TPU. Afirme que len(jax.devices())
é igual ao número de chips no seu ambiente Multislice. Para o fazer, em cada fatia, execute:
$ python3 -c 'import jax; print(jax.devices())'
Se executar este código em quatro fatias de v4-16, existem oito chips por fatia e quatro fatias, devendo ser devolvidos um total de 32 chips (dispositivos) por jax.devices()
.
Liste os recursos em fila
gcloud
Pode ver o estado dos recursos em fila de espera através do comando queued-resources list
:
$ gcloud compute tpus queued-resources list --zone=${ZONE}
O resultado tem um aspeto semelhante ao seguinte:
NAME ZONE NODE_COUNT ACCELERATOR_TYPE STATE ... que-res-id us-central1-a 4 v5litepod-16 ACTIVE ...
Consola
Inicie a tarefa num ambiente aprovisionado
Pode executar manualmente cargas de trabalho ligando-se a todos os anfitriões em cada fatia através de SSH e executando o seguinte comando em todos os anfitriões.
$ gcloud compute tpus tpu-vm ssh ${TPU_NAME} \ --zone=${ZONE} \ --worker=all \ --command="command-to-run"
Repor respostas rápidas
A API ResetQueuedResource
pode ser usada para repôr
todas as VMs num QR ACTIVE
. A reposição das VMs apaga à força a memória da máquina e repõe a VM para o respetivo estado inicial. Todos os dados armazenados localmente vão permanecer intactos, e o script de arranque vai ser invocado após uma reposição. A API
ResetQueuedResource
pode ser útil quando quer reiniciar todas as TPUs. Por exemplo, quando a preparação está bloqueada e repor todas as VMs é mais fácil do que depurar.
As reposições de todas as VMs são realizadas em paralelo e uma operação demora 1 a 2 minutos a ser concluída.ResetQueuedResource
Para invocar a API, use o seguinte comando:
$ gcloud compute tpus queued-resources reset ${QR_ID} --zone=${ZONE}
A eliminar recursos em fila
Para libertar recursos no final da sessão de formação, elimine o recurso
em fila. A eliminação demora entre dois e cinco minutos. Se estiver a usar a CLI gcloud, pode executar este comando em segundo plano com a flag --async
opcional.
gcloud
$ gcloud compute tpus queued-resources \ delete ${QR_ID} --zone=${ZONE} --force [--async]
Consola
Recuperação automática de falhas
Em caso de interrupção, o Multislice oferece uma reparação sem intervenção da fatia afetada e a reposição de todas as fatias posteriormente. A fatia afetada é substituída por uma nova fatia e as fatias restantes, que estão de outra forma em bom estado, são repostas. Se não estiver disponível capacidade para atribuir uma fatia de substituição, a preparação para.
Para retomar a preparação automaticamente após uma interrupção, tem de especificar um script de arranque que verifique e carregue os pontos de verificação guardados mais recentemente. O seu script de arranque é executado automaticamente sempre que uma fatia é reatribuída ou uma VM é reposta. Especifica um script de arranque no payload JSON que envia para a API de pedido de criação de QR.
O seguinte script de arranque (usado em Criar QRs) permite-lhe recuperar automaticamente de falhas e retomar a preparação a partir de pontos de verificação armazenados num contentor do Cloud Storage durante a preparação do MaxText:
{ "tpu": { "node_spec": [ { ... "metadata": { "startup-script": "#! /bin/bash \n pwd \n runuser -l user1 -c 'cd /home/user1/MaxText && python3 -m MaxText.train MaxText/configs/base.yml run_name=run_test_failure_recovery dcn_data_parallelism=4 ici_fsdp_parallelism=8 steps=10000 save_period=10 base_output_directory='gs://user1-us-central2'' EOF" } ... } ] } }
Clone o repositório MaxText antes de experimentar esta funcionalidade.
Criação de perfis e depuração
A criação de perfis é igual em ambientes de fatia única e de várias fatias. Para mais informações, consulte o artigo Criar perfis de programas JAX.
Otimizar a formação
As secções seguintes descrevem como pode otimizar o treino de Multislice.
Partição com várias fatias para máximo desempenho
Para alcançar o máximo desempenho em ambientes de divisão múltipla, tem de considerar como dividir os dados em vários segmentos. Normalmente, existem três opções (paralelismo de dados, paralelismo de dados totalmente fragmentados e paralelismo de pipeline). Não recomendamos a divisão de ativações pelas dimensões do modelo (por vezes, denominada paralelismo de tensores) porque requer demasiada largura de banda entre fatias. Para todas estas estratégias, pode manter a mesma estratégia de divisão em fragmentos numa fatia que funcionou para si no passado.
Recomendamos que comece com o paralelismo de dados puro. A paralelização de dados totalmente fragmentados é útil para libertar a utilização de memória. A desvantagem é que a comunicação entre as fatias usa a rede DCN e vai tornar a sua carga de trabalho mais lenta. Use o paralelismo de pipeline apenas quando necessário com base no tamanho do lote (conforme analisado abaixo).
Quando usar o paralelismo de dados
O paralelismo de dados puro funciona bem nos casos em que tem uma carga de trabalho que está a ser executada bem, mas quer melhorar o respetivo desempenho ao fazer o escalamento em várias divisões.
Para alcançar uma forte escalabilidade em várias divisões, o tempo necessário para realizar a redução total no DCN tem de ser inferior ao tempo necessário para realizar uma passagem para trás. A DCN é usada para a comunicação entre fatias e é um fator limitativo no débito da carga de trabalho.
Cada chip da TPU v4 tem um desempenho máximo de 275 * 1012 FLOPS por segundo.
Existem quatro chips por anfitrião de TPU e cada anfitrião tem uma largura de banda de rede máxima de 50 Gbps.
Isto significa que a intensidade aritmética é 4 * 275 * 1012 FLOPS / 50 Gbps = 22 000 FLOPS / bit.
O seu modelo vai usar 32 a 64 bits de largura de banda da DCN para cada parâmetro por passo. Se usar duas divisões, o modelo usa 32 bits de largura de banda da DCN. Se usar mais de duas divisões, o compilador executa uma operação de redução total de mistura completa e usa até 64 bits de largura de banda da DCN para cada parâmetro por passo. A quantidade de FLOPS necessária para cada parâmetro varia consoante o seu modelo. Especificamente, para modelos de linguagem baseados em transformadores, o número de FLOPS necessários para uma passagem para a frente e para trás é de aproximadamente 6 * B * P, onde:
O número de FLOPS por parâmetro é 6 * B
e o número de FLOPS por parâmetro
durante a passagem para trás é 4 * B
.
Para garantir uma forte escalabilidade em várias divisões, certifique-se de que a intensidade operacional excede a intensidade aritmética do hardware da TPU. Para calcular a intensidade operacional, divida o número de FLOPS por parâmetro durante a passagem para trás pela largura de banda da rede (em bits) por parâmetro por passo:
Operational Intensity = FLOPSbackwards_pass / DCN bandwidth
Por conseguinte, para um modelo de linguagem baseado em transformadores, se estiver a usar duas divisões:
Operational intensity = 4 * B / 32
Se estiver a usar mais de duas divisões: Operational intensity = 4 * B/64
Isto sugere um tamanho mínimo do lote entre 176 mil e 352 mil para modelos de linguagem baseados em transformadores. Uma vez que a rede DCN pode perder pacotes brevemente, é melhor manter uma margem de erro significativa, implementando o paralelismo de dados apenas se o tamanho do lote por Pod for, pelo menos, de 350 mil (dois Pods) a 700 mil (muitos Pods).
Para outras arquiteturas de modelos, tem de estimar o tempo de execução da passagem para trás por fatia (medindo o tempo com um perfilador ou contando FLOPS). Em seguida, pode comparar esse valor com o tempo de execução esperado para reduzir tudo no DCN e ter uma boa estimativa de se o paralelismo de dados faz sentido para si.
Quando usar o paralelismo de dados totalmente fragmentado (FSDP)
O paralelismo de dados totalmente fragmentado (FSDP) combina o paralelismo de dados (fragmentando os dados em vários nós) com a fragmentação dos pesos em vários nós. Para cada operação nas passagens para a frente e para trás, os pesos são reunidos para que cada fatia tenha os pesos de que precisa. Em vez de sincronizar os gradientes através da redução total, os gradientes são dispersos à medida que são produzidos. Desta forma, cada fatia só recebe os gradientes dos pesos pelos quais é responsável.
Semelhante ao paralelismo de dados, o FSDP requer o dimensionamento do tamanho do lote global de forma linear com o número de divisões. A FSDP diminui a pressão da memória à medida que aumenta o número de divisões. Isto deve-se ao facto de o número de ponderações e o estado do otimizador por fatia diminuírem, mas ao preço de um aumento do tráfego de rede e de uma maior possibilidade de bloqueio devido a um coletivo atrasado.
Na prática, o FSDP em fatias é melhor se estiver a aumentar o lote por fatia, a armazenar mais ativações para minimizar a rematerialização durante a passagem para trás ou a aumentar o número de parâmetros na sua rede neural.
As operações all-gather e all-reduce no FSDP funcionam de forma semelhante às do DP, pelo que pode determinar se a sua carga de trabalho do FSDP está limitada pelo desempenho da DCN da mesma forma descrita na secção anterior.
Quando usar o paralelismo de pipeline
O paralelismo de pipeline torna-se relevante quando alcança um elevado desempenho com outras estratégias de paralelismo que requerem um tamanho do lote global superior ao tamanho do lote máximo preferido. O paralelismo de pipeline permite que as divisões que compõem um pipeline "partilhem" um lote. No entanto, o paralelismo de pipeline tem duas desvantagens significativas:
O paralelismo de pipeline só deve ser usado se as outras estratégias de paralelismo exigirem um tamanho do lote global demasiado grande. Antes de experimentar o paralelismo de pipelines, vale a pena experimentar para ver empiricamente se a convergência por amostra abranda no tamanho do lote necessário para alcançar um FSDP de alto desempenho. A FSDP tende a alcançar uma utilização de FLOPs do modelo mais elevada, mas se a convergência por amostra abrandar à medida que o tamanho do lote aumenta, o paralelismo de pipeline pode continuar a ser a melhor escolha. A maioria das cargas de trabalho pode tolerar tamanhos de lotes suficientemente grandes para não beneficiar do paralelismo de pipeline, mas a sua carga de trabalho pode ser diferente.
Se o paralelismo de pipelines for necessário, recomendamos que o combine com o paralelismo de dados ou o FSDP. Isto permite-lhe minimizar a profundidade do pipeline enquanto aumenta o tamanho do lote por pipeline até que a latência da DCN se torne menos relevante no débito. Concretamente, se tiver N divisões, considere pipelines de profundidade 2 e N/2 réplicas de paralelismo de dados, depois pipelines de profundidade 4 e N/4 réplicas de paralelismo de dados, continuando da mesma forma, até que o lote por pipeline seja suficientemente grande para que os coletivos DCN possam ser ocultados atrás da aritmética na passagem para trás. Isto minimiza a desaceleração introduzida pelo paralelismo de pipeline, ao mesmo tempo que lhe permite expandir para além do limite do tamanho do lote global.
Práticas recomendadas para os multislice
As secções seguintes descrevem as práticas recomendadas para a preparação com várias fatias.
Carregamento de dados
Durante a preparação, carregamos repetidamente lotes de um conjunto de dados para introduzir no modelo. Ter um carregador de dados assíncrono eficiente que divida o lote em vários anfitriões é importante para evitar que as TPUs fiquem sem trabalho. O carregador de dados atual no MaxText faz com que cada anfitrião carregue um subconjunto igual dos exemplos. Esta solução é adequada para texto, mas requer uma nova divisão no modelo. Além disso, o MaxText ainda não oferece a criação de instantâneos determinísticos, o que permitiria ao iterador de dados carregar os mesmos dados antes e depois da preempção.
Criação de pontos de restauro
A biblioteca de pontos de verificação Orbax fornece primitivas para pontos de verificação de JAX PyTrees para armazenamento local ou Google Cloud armazenamento.
Disponibilizamos uma integração de referência com a criação de pontos de verificação síncronos no MaxText
em checkpointing.py
.
Configurações suportadas
As secções seguintes descrevem as formas de divisão suportadas, a orquestração, as frameworks e o paralelismo para o Multislice.
Formas
Todas as fatias têm de ter a mesma forma (por exemplo, o mesmo AcceleratorType
).
As formas de fatias heterogéneas não são suportadas.
Orquestração
A orquestração é suportada com o GKE. Para mais informações, consulte TPUs no GKE.
Frameworks
O Multislice só suporta cargas de trabalho JAX e PyTorch.
Paralelismo
Recomendamos que os utilizadores testem o Multislice com paralelismo de dados. Para saber mais sobre a implementação do paralelismo de pipeline com o Multislice, contacte o seu Google Cloud representante da conta.
Apoio técnico e feedback
Agradecemos todo o feedback! Para partilhar feedback ou pedir apoio técnico, contacte-nos através do formulário de apoio técnico ou feedback do Cloud TPU.