Resolução de problemas do TensorFlow – TPU

Este guia, juntamente com as Perguntas frequentes, fornece ajuda para a resolução de problemas aos utilizadores que estão a preparar modelos do TensorFlow na Cloud TPU. Se estiver a resolver problemas de formação do PyTorch ou do JAX, pode consultar os documentos de resolução de problemas desses frameworks:

Para obter guias mais gerais sobre como usar o Cloud TPU, consulte:

Vista geral

Os problemas comuns encontrados com as TPUs na nuvem enquadram-se nas seguintes categorias:

  1. Problemas ao ligar à TPU

  2. Depuração de erros comuns

  3. Reduzir a utilização de memória

  4. Melhorar a velocidade de treino

  5. Depurar diminuições na precisão do modelo

Problemas ao estabelecer ligação ao servidor da TPU

Esta secção descreve como resolver problemas em situações em que o TensorFlow deixa de responder ou imprime um erro ao estabelecer ligação à TPU. O passo de compilação do gráfico da TPU pode demorar muito tempo para modelos grandes, por isso, deixe o script ser executado durante, pelo menos, 5 minutos antes de concluir que deixou de responder.

O primeiro passo é verificar se o problema está no próprio servidor ou no pipeline de preparação do TensorFlow. Para o fazer, execute o programa TensorFlow e verifique se funciona corretamente. Se ainda existirem problemas de ligação, isto confirma que se trata de um problema com o servidor da TPU. Neste caso:

  1. Execute o seguinte comando para listar as TPUs disponíveis. Substitua zone e project-id pelo seu ID do projeto e zona.

    (vm)$ gcloud compute tpus tpu-vm list --zone zone --project project-id

    Isto imprime resultados como:

    NAME       ZONE           ACCELERATOR_TYPE  NETWORK_ENDPOINT   NETWORK  RANGE          STATUS
    TPU_NAME   us-central1-b  v2-8              10.240.1.2:8470    default  10.240.1.0  READY

  2. Verifique se esta TPU está listada como READY.

  3. Se a sua TPU não estiver listada como READY ou continuar a ter problemas de ligação, reinicie manualmente o servidor com:

    (vm)$ gcloud compute tpus tpu-vm stop TPU_NAME && gcloud compute tpus tpu-vm start TPU_NAME

    Este processo pode demorar alguns minutos.

  4. Execute novamente o comando gcloud compute tpus tpu-vm list e aguarde até que a TPU esteja no estado READY. Pode demorar alguns minutos.

  5. Tente executar o programa novamente.

  6. Se continuar a ter problemas, peça ajuda através de um dos mecanismos descritos no artigo Receber apoio técnico.

Se o código for executado corretamente, mas o modelo continuar a não responder, o problema é provavelmente com o pipeline de preparação. Para depurar este problema, comece por substituir a TPUStrategy no seu código pela estratégia predefinida. Quando usa a estratégia predefinida, sempre que usa strategy.scope() ou strategy.run(), o modelo é executado na CPU (ou na GPU, se estiver presente) em vez de na TPU. Se o modelo for executado na CPU e não na TPU, tem de existir um problema específico da TPU. Se ainda não for executado, a prática recomendada é depurar o problema na CPU.

Perda da ligação ssh durante a preparação

A sua ligação ssh à Cloud TPU pode atingir o limite de tempo durante uma sessão de preparação de longa duração (especialmente se estiver a usar o Cloud Shell). Nessa altura, não existe saída para a consola da TPU e pode parecer que a TPU parou o treino. Para evitar esta situação, execute a sessão de formação com um multiplexador de terminal ou uma ferramenta de gestão de sessões, como tmux ou screen. Isto mantém a ligação ssh ativa independentemente da duração da formação.

Depuração de erros comuns

Esta secção descreve como resolver problemas comuns que pode encontrar ao preparar modelos na Cloud TPU.

Não é possível criar uma TPU

Ao criar um TPU do Google Cloud, pode ver o seguinte erro:

googleapiclient.errors.HttpError: < HttpError 403 when requesting https://content-tpu.googleapis.com/v1/projects/{PROJECT}/locations/{ZONE}/nodes/{TPU_NAME}?alt=json returned "Request had insufficient authentication scopes."

Este é um problema de autorizações e pode ser resolvido executando o seguinte comando:

gcloud auth login --update-adc

Este comando atualiza as suas Credenciais predefinidas da aplicação (ADC) e deve resolver o problema. Para mais informações, consulte o artigo gcloud auth login.

Formas dinâmicas não suportadas

Mensagem de erro

ValueError: shape [Shape] must have a fixed size for dimension
d that is known at graph construction time.

Estruturas e configurações afetadas

Esta mensagem só ocorre durante a compilação da XLA com o TensorFlow.

Detalhes

Para executar um modelo na TPU, o Cloud TPU compila o modelo usando o compilador XLA. Embora este passo de compilação melhore significativamente a velocidade de preparação e a utilização de memória, as formas (tamanhos das dimensões) de todos os tensores no gráfico têm de ser conhecidas no momento da compilação do gráfico. Se não for possível determinar nenhuma forma no momento da compilação, a compilação da TPU falha com um erro semelhante ao apresentado anteriormente.

Uma operação comum que devolve uma forma dinâmica é dataset.batch(batch_size), uma vez que o número de amostras restantes numa stream pode ser inferior ao tamanho do lote. Por conseguinte, quando fizer a preparação na TPU, defina drop remainder=True para dataset.batch. Isto elimina potencialmente os últimos exemplos de um ficheiro para garantir que cada lote tem um formato estático de batch_size. Por exemplo:

dataset = tf.data.Dataset.range(8)
dataset = dataset.batch(3, drop_remainder=True)

Operação do TensorFlow indisponível

Mensagem de erro

NotFoundError: No registered 'OpName' OpKernel for XLA_TPU_JIT
devices compatible with node

Estruturas e configurações afetadas

Esta mensagem pode ocorrer durante a preparação com o TensorFlow.

Detalhes

O modelo usa uma operação do TensorFlow que não está disponível na TPU.

Para ver uma lista das operações disponíveis na TPU, juntamente com planos de apoio técnico futuro e sugestões de soluções alternativas, consulte o guia de operações do TensorFlow disponíveis.

Mensagem de erro de falta de memória

Mensagem de erro

ResourceExhaustedError: Ran out of memory in memory space hbm; used:
YYY; limit: 7.48G.

Estruturas e configurações afetadas

Esta mensagem pode ocorrer quando faz a preparação com o TensorFlow, o PyTorch ou o JAX.

Detalhes

Cada Cloud TPU é composto por oito núcleos de TPU. As TPUs v2 têm 8 GB e as TPUs v3 têm 16 GB de RAM (ou HBM, memória de alta largura de banda). Esta memória é usada para armazenar os tensores de peso (variáveis), bem como os tensores de resultados intermédios necessários para o cálculo do gradiente. Se o modelo for demasiado grande para caber na RAM da TPU, a inicialização falha e a mensagem de erro é impressa. Consulte a secção sobre como reduzir a utilização de memória para obter mais ajuda.

Sugestões para reduzir a utilização de memória:

Problemas ao parar a execução

Se o TensorFlow encontrar um erro durante a execução da TPU, por vezes, o script parece parar de responder em vez de sair para a shell. Se isto acontecer, prima CTRL+C no teclado para acionar um SIGQUIT, o que faz com que o Python saia imediatamente.

Da mesma forma, premir CTRL+C durante a execução da TPU não encerra o TensorFlow imediatamente, mas aguarda até ao final do ciclo de iteração atual para sair corretamente.

Se encontrar novos erros ao voltar a ligar-se à TPU depois de sair desta forma, reponha manualmente o servidor da TPU com os comandos:

gcloud compute tpus tpu-vm stop tpu-name --zone=zone
gcloud compute tpus tpu-vm start tpu-name --zone=zone

onde tpu-name é retirado da primeira coluna apresentada pelo comando gcloud compute tpus tpu-vm list e zone é a zona apresentada na segunda coluna.

Preenchimento excessivo de tensores

Causa possível do problema de memória

Os tensores na memória da TPU são preenchidos, ou seja, a TPU arredonda os tamanhos dos tensores armazenados na memória para realizar cálculos de forma mais eficiente. Este preenchimento ocorre de forma transparente ao nível do hardware e não afeta os resultados. No entanto, em determinados casos, o preenchimento pode resultar num aumento significativo da utilização de memória e do tempo de execução.

Como reduzir a utilização de memória

O software da TPU tenta organizar os tensores na memória para maximizar a eficiência computacional e minimizar o preenchimento. No entanto, este processo de esquema de memória é complexo. Para obter os melhores resultados, o modelo deve seguir a seguinte regra geral. Para minimizar a sobrecarga de memória e maximizar a eficiência computacional, tem de se verificar uma das seguintes condições:

  • O tamanho total do lote deve ser um múltiplo de 64 (8 por núcleo da TPU) e as dimensões das caraterísticas devem ser um múltiplo de 128.

    ou

  • O tamanho total do lote deve ser um múltiplo de 1024 (128 por núcleo da TPU) e as dimensões das caraterísticas devem ser um múltiplo de 8.

A utilização de um tamanho do lote de 1024 e dimensões de caraterísticas que sejam um múltiplo de 128 resulta na melhor eficiência, embora isto possa não ser possível para todos os modelos. Para maior clareza, "dimensão de caraterística" refere-se ao tamanho oculto de uma camada totalmente ligada ou ao número de canais de saída numa convolução. Nem todas as camadas podem estar em conformidade com esta regra, especialmente a primeira e a última camadas da rede. Isto é normal e espera-se que a maioria dos modelos exija alguma quantidade de preenchimento.

Reduzir a utilização de memória

Se encontrar um erro de falta de memória ao executar o modelo na TPU, tem de tomar medidas para reduzir a utilização de memória do modelo.

As formas mais eficazes de reduzir a utilização de memória são:

  • Reduza o preenchimento excessivo de tensores
  • Reduza o tamanho do lote

O tamanho do lote ou o modelo é demasiado grande

Causa possível do problema de memória

Quando treina uma rede neural numa CPU, numa GPU ou numa TPU, a utilização de memória tem origem em dois locais:

  1. A utilização de memória é proporcional ao número de ponderações no modelo.
  2. Armazenar ativações intermédias da passagem para a frente necessárias para calcular a passagem para trás. A utilização de memória é diretamente proporcional ao tamanho do lote, aos tamanhos das camadas e ao número de camadas.

Por conseguinte, a memória necessária por um modelo depende em grande medida do tamanho do lote.

A memória necessária por um modelo depende do número de camadas na rede.

O tempo de execução da TPU tenta otimizar os operadores para ajustar o modelo à memória (denominado rematerialização, semelhante à verificação de gradientes), mas nem sempre consegue fazê-lo.

Como reduzir a utilização de memória

Reduza lentamente o tamanho do lote até caber na memória, certificando-se de que o tamanho total do lote é um múltiplo de 64 (o tamanho do lote por núcleo deve ser um múltiplo de 8). Tenha em atenção que os tamanhos de lotes maiores são mais eficientes na TPU. Um tamanho total do lote de 1024 (128 por núcleo) é geralmente um bom ponto de partida.

Se não for possível executar o modelo na TPU, mesmo com um tamanho do lote pequeno (por exemplo, 64), experimente reduzir o número de camadas ou os tamanhos das camadas.

Melhorar a velocidade de preparação

Se o seu modelo conseguir ser executado com êxito na TPU, mas a velocidade de preparação for inferior à esperada, esta secção descreve várias formas potenciais de melhorar a velocidade. Consulte o guia de desempenho para ver outras sugestões sobre como melhorar o desempenho da preparação.

Demasiados poucos passos por execução por ciclo de preparação

Descrição do problema de desempenho

A transmissão do argumento steps_per_execution para Model.compile controla o número de passos de preparação executados entre as chamadas de retorno do anfitrião. Cada callback do anfitrião requer uma comunicação significativa entre a CPU do anfitrião do servidor de TPU e o dispositivo de TPU. Por isso, se steps_per_execution for demasiado pequeno, pode abrandar o treino.

Como saber se o seu modelo é afetado

Se um perfil de TPU revelar chamadas de retorno frequentes da CPU do anfitrião entre os passos do dispositivo TPU, o seu treino pode beneficiar de um valor steps_per_execution maior.

Como mitigar

Defina steps_per_execution para um valor maior. Tenha em atenção que steps_per_execution pode ser definido para um valor elevado, mas tenha em atenção que as mensagens de registo e a gravação de um ponto de verificação só podem ocorrer após a execução do número especificado de passos.

Gargalo de processamento de entrada

Descrição do problema de desempenho

Enquanto a TPU está a preparar um determinado bloco de dados, a função de processamento de entrada prepara o bloco de dados seguinte na CPU. Se a sua função de entrada demorar mais tempo do que a função do modelo, a TPU fica inativa enquanto a função de entrada está a obter dados.

Como saber se o seu modelo é afetado

Siga as instruções em Cloud TPU Tools: Input Pipeline Analyzer para ver a análise da pipeline de entrada no TensorBoard:

imagem

A página de análise do pipeline de entrada apresenta um resumo claro que mostra se o seu modelo está limitado pelo processamento de entrada. A mesma página também mostra o tempo de execução por operação, o que lhe permite identificar operações problemáticas.

Como mitigar

Existem várias mitigações possíveis ao carregar dados com a API Dataset:

  1. Armazene os seus dados como uma coleção de estruturas tf.train.Example em ficheiros TFRecord e carregue-os com TFRecordDataset. Consulte o tutorial da API Dataset ou o tutorial da ResNet para ver exemplos.
  2. Use dataset.cache() ou dataset.prefetch() para colocar os dados de entrada em buffer. Isto impede que as lentidões esporádicas no acesso a ficheiros criem um gargalo.
  3. Especifique o parâmetro num_parallel_calls da função dataset.map() para ativar as operações map() com várias linhas. Uma heurística para o valor de num_parallel_calls é usar o número de núcleos da CPU disponíveis.
  4. Realize o pré-processamento de dados dispendioso offline como um custo único, em vez de incorrer no custo em cada época de cada preparação.

Todo o processamento de entradas é realizado em CPUs localizadas no servidor de TPU e não na máquina local, pelo que a velocidade da máquina local não é um fator.

Tempos de passos lentos e baixa utilização da MXU

Descrição do problema de desempenho

A Cloud TPU pode realizar multiplicações de matrizes e convoluções a velocidades incrivelmente elevadas. A maioria das outras operações do TensorFlow tem implementações eficientes na TPU, mas estas não são a principal vantagem da TPU em relação a outro hardware. Por conseguinte, um modelo deve ser dominado por multiplicações de matrizes ou convoluções para tirar total partido da TPU.

Como saber se o seu modelo é afetado

Neste caso, os sintomas que vai observar são tempos de passos lentos, juntamente com uma utilização baixa da MXU apresentada quando analisa o desempenho.

Como mitigar

Experimente reduzir o número de operações que não são multiplicações de matrizes. Depois de reduzir o número de multiplicações de matrizes, faça novamente o teste de referência para ver se o desempenho é aceitável nas TPUs.

Preenchimento excessivo de tensores

Descrição do problema de desempenho

A TPU preenche os tensores na memória para que a TPU possa usar as respetivas unidades computacionais de forma eficiente. O preenchimento pode aumentar a utilização da memória e da largura de banda da memória. Consulte a secção sobre o preenchimento de tensores para obter ajuda na compreensão e correção de problemas de preenchimento de tensores.

Débito lento e utilização de memória baixa

Descrição do problema de desempenho

Como regra geral, a utilização de tamanhos de lotes maiores resulta numa maior velocidade de preparação na TPU, em termos de exemplos/segundo.

Como saber se o seu modelo é afetado

O tamanho do lote de qualquer modelo deve ser sempre, pelo menos, 64 (8 por núcleo da TPU), uma vez que a TPU preenche sempre os tensores até este tamanho. O tamanho ideal do lote quando faz o treino na TPU é 1024 (128 por núcleo da TPU), uma vez que elimina ineficiências relacionadas com a transferência de memória e o preenchimento.

Como mitigar

A prática recomendada é usar o maior tamanho do lote que se ajuste à memória e seja um múltiplo de 64. A forma mais fácil de o conseguir é começar com 1024 e, se isto causar um erro de falta de memória, tente reduzir o tamanho do lote até o modelo ser executado com êxito. Alterar o tamanho do lote de um modelo pode exigir o ajuste de outros hiperparâmetros para alcançar a mesma precisão do modelo, como a taxa de aprendizagem, mas isto tem de ser avaliado caso a caso.

Os tamanhos das camadas são demasiado pequenos

Descrição do problema de desempenho

Mesmo quando um modelo é dominado por multiplicações de matrizes ou convoluções, a TPU pode não ser executada com eficiência total se os tensores de entrada forem pequenos. Quando comparada com outro hardware, a TPU funciona de forma mais eficiente quando o tamanho do lote e os tamanhos das camadas são grandes (por exemplo, dimensão >= 512).

Como saber se o seu modelo é afetado

Como regra geral, os tamanhos de camadas inferiores a 128 alcançam uma eficiência fraca na TPU, uma vez que 128 é a dimensão incorporada da unidade de multiplicação de matrizes da TPU. Para camadas totalmente ligadas, recomenda-se um tamanho oculto mínimo de 512 para alcançar uma elevada eficiência. Tenha em atenção que, normalmente, as camadas convolucionais não têm de ser tão grandes como as camadas totalmente ligadas para alcançar um nível de eficiência igual.

Como mitigar

Se a principal motivação para tamanhos de camadas pequenos no seu modelo for a velocidade de preparação, volte a testar os seus modelos com camadas maiores na TPU. Por exemplo, aumentar o tamanho da saída de uma camada de 256 para 512 pode apenas aumentar o tempo de preparação em 20%, mesmo que o modelo esteja a realizar o dobro dos cálculos.

Criação de perfis de modelos ao nível da operação

É frequentemente útil medir o tempo de execução ao nível da operação e a utilização de memória para identificar gargalos de desempenho. Para ver instruções sobre como o fazer,
consulte o guia Ferramentas Cloud TPU: Trace Viewer.

Depurar diminuições na precisão do modelo

Um dos objetivos do ecossistema Cloud TPU é que qualquer modelo que esteja a ser preparado numa CPU ou numa GPU alcance uma precisão muito semelhante quando é preparado na TPU, com possíveis ajustes menores aos hiperparâmetros, como o tamanho do lote e a taxa de aprendizagem. No entanto, ocasionalmente, os utilizadores podem observar uma degradação na precisão quando preparam modelos na TPU. A depuração destes problemas pode ser extremamente frustrante devido à natureza aleatória da preparação da rede neural. Esta secção fornece orientações sobre como identificar a causa principal de quaisquer diminuições na precisão do modelo ao transferir um modelo para a TPU.

Compreender a divisão de dados (paralelismo de dados)

Um dos principais objetivos do TensorFlow é que cada operação produza resultados quase idênticos, quer seja executada na CPU, na GPU ou na TPU. Existem determinadas exceções a esta regra, como operações aleatórias. Em geral, se encontrar alguma diferença significativa entre o resultado das operações não aleatórias na TPU e na CPU, comunique-a como um erro.

No entanto, para o pipeline de preparação como um todo, existe uma diferença significativa entre a preparação na CPU/GPU e na TPU. Quando faz a preparação numa TPU, o TensorFlow realiza a divisão de dados. Cada Cloud TPU contém 8 núcleos de TPU que funcionam como unidades de processamento independentes. Para cada passo na preparação, cada núcleo da TPU recebe um lote de dados, calcula os gradientes de ponderação, troca os gradientes com os outros núcleos da TPU e, em seguida, calcula a atualização da ponderação. Por predefinição, a perda é calculada como a média entre os núcleos, mas pode ser somada alterando o parâmetro de CrossShardOptimizer.

Se a perda total do modelo puder ser calculada como a média (ou a soma) das perdas independentes por amostra, este procedimento é matematicamente equivalente à preparação num único lote grande.

A operação mais comum que não é independente por amostra é a normalização de lotes, que é executada em cada lote por núcleo separadamente. Por exemplo, se o tamanho total do lote for 128, o tamanho do lote por núcleo é 16 e cada um dos 8 núcleos executa a normalização do lote nas suas próprias 16 amostras. Em alguns casos, a realização da normalização em lote em pequenos lotes (por exemplo, menos de 32) demonstrou degradar a precisão. No cenário ideal, o tamanho total do lote deve ser elevado (por exemplo, 256 a 1024). Se o tamanho de um lote for demasiado grande para caber na memória, o efeito da divisão tem de ser avaliado caso a caso.

Depuração do treino de TPU com vários núcleos

Se o seu modelo atingir a mesma perda na CPU e na TPU de núcleo único, é provável que o problema seja um dos seguintes:

(a) A degradação deve-se à variância aleatória natural quando se preparam modelos neurais com inicializações diferentes.

(b) A degradação deve-se a um problema relacionado com a divisão de dados na TPU.

Para determinar se (a) é o problema, volte a preparar o modelo completo na CPU/GPU e na TPU de vários núcleos com a mesma inicialização de ponderação.

Se tiver a certeza de que a diminuição da precisão é estatisticamente significativa, os problemas mais prováveis relacionados com a divisão de dados são:

  1. Se o seu modelo usar a normalização de lotes, um tamanho total do lote inferior a 256 (por exemplo, inferior a 32 por núcleo) pode reduzir a precisão.
  2. As funções de perda por lote são afetadas pela divisão. Normalmente, estas funções de perda são bastante especializadas. Por exemplo, Karras et al. 2017 usa um discriminador de lotes ao preparar uma rede antagónica generativa.

gcloud Resolução de problemas de configuração

Problema
gcloud components update apresenta a seguinte mensagem de erro:
ERROR: (gcloud.components.update)
You cannot perform this action because the Cloud SDK component manager is
disabled for this installation.
Solução

Para usar a Google Cloud CLI, tem de usar uma instalação que não seja gerida através de um gestor de pacotes.

  1. Execute o seguinte comando para remover a instalação atual da CLI gcloud:

    sudo apt-get remove google-cloud-sdk
  2. Siga as instruções para instalar a CLI Google Cloud.

Problema

O comando gcloud compute tpus tpu-vm ssh TPU_NAME --zone ZONE apresenta a seguinte mensagem de erro:

Waiting for SSH key to propagate.
ssh: connect to host 34.91.136.59 port 22: Connection timed out
ssh: connect to host 34.91.136.59 port 22: Connection timed out
ssh: connect to host 34.91.136.59 port 22: Connection timed out
ERROR: (gcloud.compute.tpus.tpu-vm.ssh) Could not SSH into the instance.  It is possible that your SSH key has not propagated to the instance yet. Try running this command again.  If you still cannot connect, verify that the firewall and instance are set to accept ssh traffic.
Solução

Pode haver um problema com a propagação da chave SSH. Experimente mover as chaves geradas automaticamente para uma localização de cópia de segurança para forçar o gcloud a recriá-las:

mv ~/.ssh/google_compute_engine ~/.ssh/old-google_compute_engine
mv ~/.ssh/google_compute_engine.pub ~/.ssh/old-google_compute_engine.pub

Registos de depuração

As frameworks da Cloud TPU suportadas, JAX, PyTorch e TensorFlow, acedem às TPUs através de uma biblioteca partilhada denominada libtpu, que está presente em todas as VMs da TPU. Esta biblioteca inclui o compilador XLA usado para compilar programas de TPU, o tempo de execução de TPU usado para executar programas compilados e o controlador de TPU usado pelo tempo de execução para acesso de baixo nível à TPU.

A biblioteca libtpu regista informações que podem ser úteis para a depuração. Por predefinição, estes registos são escritos em /tmp/tpu_logs em cada VM da Cloud TPU. As seguintes variáveis de ambiente podem ser definidas antes de iniciar a preparação para modificar o comportamento de registo:

TPU_LOG_DIR: o diretório no qual os registos são escritos
A localização do diretório é predefinida como /tmp/tpu_logs. O diretório é criado se ainda não existir, mas não são criados diretórios principais. Se ocorrer um erro ao encontrar ou criar o diretório especificado, é apresentada uma mensagem em stderr, mas o programa não é interrompido e o registo é desativado. Defina o nome do diretório como "disabled" para desativar completamente o registo em disco.
TPU_MIN_LOG_LEVEL: a gravidade mínima que vai ser registada em disco
As opções são 0 (INFO), 1 (AVISO), 2 (ERRO) e 3 (FATAL). O valor predefinido é 0.
TPU_STDERR_LOG_LEVEL: a gravidade mínima que vai ser registada no stderr, além do disco, se aplicável
As opções são as mesmas que TPU_MIN_LOG_LEVEL. O valor predefinido é 3.
TPU_MAX_LOG_SIZE_MB: o tamanho máximo em megabytes de cada ficheiro de registo
É iniciado automaticamente um novo ficheiro de registo quando o anterior atinge aproximadamente este tamanho. A predefinição é 1024.