Otimize o desempenho do TensorFlow usando o Profiler

Este guia demonstra como usar as ferramentas disponíveis com o TensorFlow Profiler para acompanhar o desempenho de seus modelos do TensorFlow. Você aprenderá como entender o desempenho do seu modelo no host (CPU), no dispositivo (GPU) ou em uma combinação do host e do(s) dispositivo(s).

A criação de perfil ajuda a entender o consumo de recursos de hardware (tempo e memória) das várias operações do TensorFlow (ops) em seu modelo e resolver gargalos de desempenho e, por fim, tornar o modelo mais rápido.

Este guia orientará você sobre como instalar o Profiler, as várias ferramentas disponíveis, os diferentes modos de como o Profiler coleta dados de desempenho e algumas práticas recomendadas para otimizar o desempenho do modelo.

Se você quiser criar o perfil do desempenho do seu modelo em Cloud TPUs, consulte o guia do Cloud TPU .

Instale os pré-requisitos do Profiler e da GPU

Instale o plug-in Profiler para TensorBoard com pip. Observe que o Profiler requer as versões mais recentes do TensorFlow e do TensorBoard (>=2.2).

pip install -U tensorboard_plugin_profile

Para criar perfil na GPU, você deve:

  1. Atenda aos drivers NVIDIA® GPU e aos requisitos do CUDA® Toolkit listados nos requisitos de software de suporte a GPU TensorFlow .
  2. Certifique-se de que a Interface de ferramentas de criação de perfil NVIDIA® CUDA® (CUPTI) exista no caminho:

    /sbin/ldconfig -N -v $(sed 's/:/ /g' <<< $LD_LIBRARY_PATH) | \
    grep libcupti
    

Se você não tiver CUPTI no caminho, anexe seu diretório de instalação à variável de ambiente $LD_LIBRARY_PATH executando:

export LD_LIBRARY_PATH=/usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH

Em seguida, execute o comando ldconfig acima novamente para verificar se a biblioteca CUPTI foi encontrada.

Resolver problemas de privilégio

Ao executar a criação de perfil com o CUDA® Toolkit em um ambiente Docker ou no Linux, você pode encontrar problemas relacionados a privilégios CUPTI insuficientes ( CUPTI_ERROR_INSUFFICIENT_PRIVILEGES ). Acesse os Documentos para desenvolvedores da NVIDIA para saber mais sobre como resolver esses problemas no Linux.

Para resolver problemas de privilégio CUPTI em um ambiente Docker, execute

docker run option '--privileged=true'

Ferramentas do criador de perfil

Acesse o Profiler na guia Profile no TensorBoard, que aparece somente depois que você captura alguns dados do modelo.

O Profiler tem uma seleção de ferramentas para ajudar na análise de desempenho:

  • Página de visão geral
  • Analisador de pipeline de entrada
  • Estatísticas do TensorFlow
  • Visualizador de rastreamento
  • Estatísticas do kernel da GPU
  • Ferramenta de perfil de memória
  • Visualizador de pod

Página de visão geral

A página de visão geral fornece uma visão de nível superior de como seu modelo foi executado durante uma execução de perfil. A página mostra uma página de visão geral agregada para seu host e todos os dispositivos, e algumas recomendações para melhorar o desempenho do treinamento do seu modelo. Você também pode selecionar hosts individuais no menu suspenso Host.

A página de visão geral exibe os dados da seguinte forma:

imagem

  • Resumo do desempenho : exibe um resumo de alto nível do desempenho do seu modelo. O resumo de desempenho tem duas partes:

    1. Detalhamento do tempo da etapa: divide o tempo médio da etapa em várias categorias de onde o tempo é gasto:

      • Compilação: Tempo gasto compilando kernels.
      • Entrada: Tempo gasto na leitura dos dados de entrada.
      • Saída: Tempo gasto na leitura dos dados de saída.
      • Lançamento do kernel: tempo gasto pelo host para iniciar kernels
      • Tempo de computação do host..
      • Tempo de comunicação de dispositivo para dispositivo.
      • Tempo de computação no dispositivo.
      • Todos os outros, incluindo a sobrecarga do Python.
    2. Precisões de computação do dispositivo - relata a porcentagem de tempo de computação do dispositivo que usa cálculos de 16 e 32 bits.

  • Step-time Graph : Exibe um gráfico do tempo de passo do dispositivo (em milissegundos) em todos os passos amostrados. Cada etapa é dividida em várias categorias (com cores diferentes) de onde o tempo é gasto. A área vermelha corresponde à parte do tempo da etapa em que os dispositivos ficaram ociosos aguardando dados de entrada do host. A área verde mostra por quanto tempo o dispositivo estava realmente funcionando.

  • As 10 principais operações do TensorFlow no dispositivo (por exemplo, GPU) : exibe as operações no dispositivo que foram executadas por mais tempo.

    Cada linha exibe o tempo próprio de uma operação (como a porcentagem de tempo gasto por todas as operações), tempo cumulativo, categoria e nome.

  • Ambiente de execução : exibe um resumo de alto nível do ambiente de execução do modelo, incluindo:

    • Número de hosts usados.
    • Tipo de dispositivo (GPU/TPU).
    • Número de núcleos do dispositivo.
  • Recomendação para a próxima etapa : relata quando um modelo é vinculado à entrada e recomenda ferramentas que você pode usar para localizar e resolver gargalos de desempenho do modelo.

Analisador de pipeline de entrada

Quando um programa do TensorFlow lê dados de um arquivo, ele começa na parte superior do gráfico do TensorFlow de maneira pipeline. O processo de leitura é dividido em vários estágios de processamento de dados conectados em série, onde a saída de um estágio é a entrada para o próximo. Esse sistema de leitura de dados é chamado de pipeline de entrada .

Um pipeline típico para ler registros de arquivos tem os seguintes estágios:

  1. Leitura de arquivo.
  2. Pré-processamento de arquivos (opcional).
  3. Transferência de arquivos do host para o dispositivo.

Um pipeline de entrada ineficiente pode desacelerar severamente seu aplicativo. Um aplicativo é considerado vinculado à entrada quando passa uma parte significativa do tempo no pipeline de entrada. Use os insights obtidos do analisador de pipeline de entrada para entender onde o pipeline de entrada é ineficiente.

O analisador de pipeline de entrada informa imediatamente se seu programa está vinculado à entrada e orienta você pela análise do lado do dispositivo e do host para depurar gargalos de desempenho em qualquer estágio do pipeline de entrada.

Verifique a orientação sobre o desempenho do pipeline de entrada para obter as práticas recomendadas para otimizar seus pipelines de entrada de dados.

Painel de pipeline de entrada

Para abrir o analisador de pipeline de entrada, selecione Perfil e, em seguida, selecione input_pipeline_analyzer no menu suspenso Ferramentas .

imagem

O painel contém três seções:

  1. Resumo : Resume o pipeline de entrada geral com informações sobre se seu aplicativo está vinculado à entrada e, em caso afirmativo, por quanto.
  2. Análise do lado do dispositivo : exibe resultados detalhados da análise do lado do dispositivo, incluindo o tempo da etapa do dispositivo e o intervalo de tempo do dispositivo gasto aguardando dados de entrada nos núcleos em cada etapa.
  3. Análise do lado do host : mostra uma análise detalhada do lado do host, incluindo um detalhamento do tempo de processamento de entrada no host.

Resumo do pipeline de entrada

O Resumo informa se o seu programa está vinculado à entrada, apresentando a porcentagem de tempo do dispositivo gasto aguardando entrada do host. Se você estiver usando um pipeline de entrada padrão que foi instrumentado, a ferramenta informará onde a maior parte do tempo de processamento de entrada é gasta.

Análise do lado do dispositivo

A análise do lado do dispositivo fornece informações sobre o tempo gasto no dispositivo versus no host e quanto tempo do dispositivo foi gasto aguardando dados de entrada do host.

  1. Tempo da etapa plotado em relação ao número da etapa : Exibe um gráfico do tempo da etapa do dispositivo (em milissegundos) em todas as etapas amostradas. Cada etapa é dividida em várias categorias (com cores diferentes) de onde o tempo é gasto. A área vermelha corresponde à parte do tempo da etapa em que os dispositivos ficaram ociosos aguardando dados de entrada do host. A área verde mostra por quanto tempo o dispositivo estava realmente funcionando.
  2. Estatísticas de tempo de passo : relata a média, desvio padrão e intervalo ([mínimo, máximo]) do tempo de passo do dispositivo.

Análise do lado do host

A análise do lado do host relata um detalhamento do tempo de processamento de entrada (o tempo gasto nas operações da API tf.data ) no host em várias categorias:

  • Lendo dados de arquivos sob demanda : tempo gasto na leitura de dados de arquivos sem armazenamento em cache, pré-busca e intercalação.
  • Lendo dados de arquivos com antecedência : tempo gasto lendo arquivos, incluindo armazenamento em cache, pré-busca e intercalação.
  • Pré- processamento de dados : tempo gasto em operações de pré-processamento, como descompactação de imagem.
  • Enfileiramento de dados a serem transferidos para o dispositivo : Tempo gasto colocando dados em uma fila de entrada antes de transferir os dados para o dispositivo.

Expanda Estatísticas de operações de entrada para inspecionar as estatísticas de operações de entrada individuais e suas categorias divididas por tempo de execução.

imagem

Uma tabela de dados de origem aparecerá com cada entrada contendo as seguintes informações:

  1. Input Op : mostra o nome da operação TensorFlow da operação de entrada.
  2. Contagem : mostra o número total de instâncias de execução de operações durante o período de criação de perfil.
  3. Tempo total (em ms) : mostra a soma cumulativa do tempo gasto em cada uma dessas instâncias.
  4. % de tempo total : mostra o tempo total gasto em uma operação como uma fração do tempo total gasto no processamento de entrada.
  5. Total Self Time (em ms) : Mostra a soma cumulativa do self time gasto em cada uma dessas instâncias. O tempo próprio aqui mede o tempo gasto dentro do corpo da função, excluindo o tempo gasto na função que ele chama.
  6. % de Tempo Próprio Total . Mostra o tempo total próprio como uma fração do tempo total gasto no processamento de entrada.
  7. Categoria . Mostra a categoria de processamento do op de entrada.

Estatísticas do TensorFlow

A ferramenta TensorFlow Stats exibe o desempenho de cada operação (op) do TensorFlow executada no host ou dispositivo durante uma sessão de criação de perfil.

imagem

A ferramenta exibe informações de desempenho em dois painéis:

  • O painel superior exibe até quatro gráficos de pizza:

    1. A distribuição do tempo de autoexecução de cada operação no host.
    2. A distribuição do tempo de autoexecução de cada tipo de operação no host.
    3. A distribuição do tempo de autoexecução de cada operação no dispositivo.
    4. A distribuição do tempo de autoexecução de cada tipo de operação no dispositivo.
  • O painel inferior mostra uma tabela que relata dados sobre as operações do TensorFlow com uma linha para cada operação e uma coluna para cada tipo de dados (classifique as colunas clicando no título da coluna). Clique no botão Exportar como CSV no lado direito do painel superior para exportar os dados desta tabela como um arquivo CSV.

    Observe que:

    • Se alguma operação tiver operações filhas:

      • O tempo total "acumulado" de uma operação inclui o tempo gasto nas operações filhas.
      • O tempo total "próprio" de uma operação não inclui o tempo gasto dentro das operações filhas.
    • Se uma operação for executada no host:

      • A porcentagem do tempo total no dispositivo incorrida pela opção será 0.
      • A porcentagem cumulativa do tempo total no dispositivo até e incluindo esta operação será 0.
    • Se uma operação for executada no dispositivo:

      • A porcentagem do tempo total no host incorrida por esta operação será 0.
      • A porcentagem cumulativa do tempo total no host até e incluindo esta operação será 0.

Você pode optar por incluir ou excluir o tempo ocioso nos gráficos de pizza e na tabela.

Visualizador de rastreamento

O visualizador de rastreamento exibe uma linha do tempo que mostra:

  • Durações das operações executadas pelo seu modelo do TensorFlow
  • Qual parte do sistema (host ou dispositivo) executou uma operação. Normalmente, o host executa operações de entrada, pré-processa dados de treinamento e os transfere para o dispositivo, enquanto o dispositivo executa o treinamento do modelo real.

O visualizador de rastreamento permite identificar problemas de desempenho em seu modelo e, em seguida, executar etapas para resolvê-los. Por exemplo, em um nível alto, você pode identificar se o treinamento de entrada ou modelo está tomando a maior parte do tempo. Aprofundando, você pode identificar quais operações demoram mais para serem executadas. Observe que o visualizador de rastreamento está limitado a 1 milhão de eventos por dispositivo.

Interface do visualizador de rastreamento

Quando você abre o visualizador de rastreamento, ele aparece exibindo sua execução mais recente:

imagem

Esta tela contém os seguintes elementos principais:

  1. Painel de linha do tempo : mostra as operações que o dispositivo e o host executaram ao longo do tempo.
  2. Painel de detalhes : mostra informações adicionais para operações selecionadas no painel Linha do tempo.

O painel Linha do tempo contém os seguintes elementos:

  1. Barra superior : Contém vários controles auxiliares.
  2. Eixo do tempo : Mostra o tempo relativo ao início do traço.
  3. Rótulos de seção e trilha : cada seção contém várias trilhas e tem um triângulo à esquerda que você pode clicar para expandir e recolher a seção. Há uma seção para cada elemento de processamento no sistema.
  4. Seletor de ferramentas : contém várias ferramentas para interagir com o visualizador de rastreamento, como Zoom, Pan, Select e Timing. Use a ferramenta Tempo para marcar um intervalo de tempo.
  5. Eventos : mostram o tempo durante o qual uma operação foi executada ou a duração de meta-eventos, como etapas de treinamento.
Seções e faixas

O visualizador de rastreamento contém as seguintes seções:

  • Uma seção para cada nó de dispositivo , rotulada com o número do chip do dispositivo e o nó do dispositivo dentro do chip (por exemplo, /device:GPU:0 (pid 0) ). Cada seção do nó do dispositivo contém as seguintes faixas:
    • Etapa : Mostra a duração das etapas de treinamento que estavam sendo executadas no dispositivo
    • TensorFlow Ops : mostra as operações executadas no dispositivo
    • XLA Ops : mostra as operações XLA (ops) executadas no dispositivo se XLA for o compilador usado (cada operação TensorFlow é traduzida em uma ou várias operações XLA. O compilador XLA traduz as operações XLA em código executado no dispositivo).
  • Uma seção para threads em execução na CPU da máquina host, rotulada "Host Threads" . A seção contém uma trilha para cada thread da CPU. Observe que você pode ignorar as informações exibidas ao lado dos rótulos das seções.
Eventos

Os eventos na linha do tempo são exibidos em cores diferentes; as próprias cores não têm significado específico.

O visualizador de rastreamento também pode exibir rastreamentos de chamadas de função Python em seu programa TensorFlow. Se você usar a API tf.profiler.experimental.start , poderá habilitar o rastreamento do Python usando a tupla nomeada ProfilerOptions ao iniciar a criação de perfil. Como alternativa, se você usar o modo de amostragem para criação de perfil, poderá selecionar o nível de rastreamento usando as opções suspensas na caixa de diálogo Capturar perfil .

imagem

Estatísticas do kernel da GPU

Essa ferramenta mostra estatísticas de desempenho e a operação de origem para cada kernel acelerado por GPU.

imagem

A ferramenta exibe informações em dois painéis:

  • O painel superior exibe um gráfico de pizza que mostra os kernels CUDA que têm o maior tempo total decorrido.

  • O painel inferior exibe uma tabela com os seguintes dados para cada par kernel-op exclusivo:

    • Uma classificação em ordem decrescente da duração total da GPU decorrida agrupada por par kernel-op.
    • O nome do kernel lançado.
    • O número de registros de GPU usados ​​pelo kernel.
    • O tamanho total da memória compartilhada (estática + dinâmica compartilhada) usada em bytes.
    • A dimensão do bloco expressa como blockDim.x, blockDim.y, blockDim.z .
    • As dimensões da grade expressas como gridDim.x, gridDim.y, gridDim.z .
    • Se a operação está qualificada para usar Tensor Cores .
    • Se o kernel contém instruções do Tensor Core.
    • O nome do op que lançou este kernel.
    • O número de ocorrências desse par kernel-op.
    • O tempo total decorrido da GPU em microssegundos.
    • O tempo médio decorrido da GPU em microssegundos.
    • O tempo mínimo decorrido da GPU em microssegundos.
    • O tempo máximo decorrido da GPU em microssegundos.

Ferramenta de perfil de memória

A ferramenta Memory Profile monitora o uso de memória do seu dispositivo durante o intervalo de criação de perfil. Você pode usar esta ferramenta para:

  • Depure problemas de falta de memória (OOM) identificando o pico de uso de memória e a alocação de memória correspondente para as operações do TensorFlow. Você também pode depurar problemas de OOM que podem surgir ao executar a inferência de multilocação .
  • Depure problemas de fragmentação de memória.

A ferramenta de perfil de memória exibe dados em três seções:

  1. Resumo do perfil de memória
  2. Gráfico de linha do tempo de memória
  3. Tabela de Detalhamento de Memória

Resumo do perfil de memória

Esta seção exibe um resumo de alto nível do perfil de memória do seu programa TensorFlow, conforme mostrado abaixo:

O resumo do perfil de memória tem seis campos:

  1. Memory ID : Lista suspensa que lista todos os sistemas de memória do dispositivo disponíveis. Selecione o sistema de memória que deseja visualizar no menu suspenso.
  2. #Allocation : O número de alocações de memória feitas durante o intervalo de criação de perfil.
  3. #Deallocation : O número de desalocações de memória no intervalo de criação de perfil
  4. Memory Capacity : A capacidade total (em GiBs) do sistema de memória que você selecionar.
  5. Peak Heap Usage : O pico de uso de memória (em GiBs) desde que o modelo começou a ser executado.
  6. Peak Memory Usage : O pico de uso de memória (em GiBs) no intervalo de criação de perfil. Este campo contém os seguintes subcampos:
    1. Timestamp : O timestamp de quando o pico de uso de memória ocorreu no Timeline Graph.
    2. Stack Reservation : Quantidade de memória reservada na pilha (em GiBs).
    3. Heap Allocation : Quantidade de memória alocada no heap (em GiBs).
    4. Memória Livre : Quantidade de memória livre (em GiBs). A Capacidade de Memória é a soma total da Reserva de Pilha, Alocação de Heap e Memória Livre.
    5. Fragmentação : A porcentagem de fragmentação (menor é melhor). É calculado como uma porcentagem de (1 - Size of the largest chunk of free memory / Total free memory) .

Gráfico de linha do tempo de memória

Esta seção exibe um gráfico do uso de memória (em GiBs) e a porcentagem de fragmentação versus tempo (em ms).

imagem

O eixo X representa a linha do tempo (em ms) do intervalo de criação de perfil. O eixo Y à esquerda representa o uso de memória (em GiBs) e o eixo Y à direita representa a porcentagem de fragmentação. Em cada momento no eixo X, a memória total é dividida em três categorias: pilha (em vermelho), heap (em laranja) e livre (em verde). Passe o mouse sobre um carimbo de data/hora específico para ver os detalhes sobre os eventos de alocação/desalocação de memória naquele ponto, como abaixo:

imagem

A janela pop-up exibe as seguintes informações:

  • timestamp(ms) : A localização do evento selecionado na linha do tempo.
  • event : O tipo de evento (alocação ou desalocação).
  • request_size(GiBs) : A quantidade de memória solicitada. Este será um número negativo para eventos de desalocação.
  • location_size(GiBs) : A quantidade real de memória alocada. Este será um número negativo para eventos de desalocação.
  • tf_op : O op TensorFlow que solicita a alocação/desalocação.
  • step_id : a etapa de treinamento na qual esse evento ocorreu.
  • region_type : O tipo de entidade de dados para o qual esta memória alocada é. Os valores possíveis são temp para temporários, output para ativações e gradientes e persist / dynamic para pesos e constantes.
  • data_type : O tipo de elemento tensor (por exemplo, uint8 para inteiro sem sinal de 8 bits).
  • tensor_shape : A forma do tensor que está sendo alocado/desalocado.
  • memory_in_use(GiBs) : A memória total que está em uso neste momento.

Tabela de quebra de memória

Esta tabela mostra as alocações de memória ativa no ponto de pico de uso de memória no intervalo de criação de perfil.

imagem

Há uma linha para cada TensorFlow Op e cada linha tem as seguintes colunas:

  • Nome da operação : o nome da operação do TensorFlow.
  • Allocation Size (GiBs) : A quantidade total de memória alocada para esta operação.
  • Tamanho solicitado (GiBs) : A quantidade total de memória solicitada para esta operação.
  • Ocorrências : O número de alocações para esta operação.
  • Tipo de região : O tipo de entidade de dados para o qual esta memória alocada se destina. Os valores possíveis são temp para temporários, output para ativações e gradientes e persist / dynamic para pesos e constantes.
  • Tipo de dados : O tipo de elemento tensor.
  • Shape : A forma dos tensores alocados.

Visualizador de pod

A ferramenta Pod Viewer mostra o detalhamento de uma etapa de treinamento em todos os trabalhadores.

imagem

  • O painel superior tem um controle deslizante para selecionar o número da etapa.
  • O painel inferior exibe um gráfico de colunas empilhadas. Esta é uma visão de alto nível de categorias de tempo de etapa divididas colocadas umas sobre as outras. Cada coluna empilhada representa um trabalhador único.
  • Quando você passa o mouse sobre uma coluna empilhada, o cartão do lado esquerdo mostra mais detalhes sobre o detalhamento da etapa.

análise de gargalo tf.data

A ferramenta de análise de gargalos tf.data detecta automaticamente gargalos nos pipelines de entrada tf.data em seu programa e fornece recomendações sobre como corrigi-los. Funciona com qualquer programa usando tf.data independente da plataforma (CPU/GPU/TPU). Sua análise e recomendações são baseadas neste guia .

Ele detecta um gargalo seguindo estas etapas:

  1. Encontre o host mais ligado à entrada.
  2. Encontre a execução mais lenta de um pipeline de entrada tf.data .
  3. Reconstrua o gráfico de pipeline de entrada do rastreamento do criador de perfil.
  4. Encontre o caminho crítico no gráfico do pipeline de entrada.
  5. Identifique a transformação mais lenta no caminho crítico como um gargalo.

A interface do usuário é dividida em três seções: Resumo da análise de desempenho , Resumo de todos os pipelines de entrada e Gráfico do pipeline de entrada .

Resumo da análise de desempenho

imagem

Esta seção fornece o resumo da análise. Ele relata sobre pipelines de entrada tf.data lentos detectados no perfil. Esta seção também mostra o host mais ligado à entrada e seu pipeline de entrada mais lento com a latência máxima. Mais importante, ele identifica qual parte do pipeline de entrada é o gargalo e como corrigi-lo. As informações de gargalo são fornecidas com o tipo de iterador e seu nome longo.

Como ler o nome longo do iterador tf.data

Um nome longo é formatado como Iterator::<Dataset_1>::...::<Dataset_n> . No nome longo, <Dataset_n> corresponde ao tipo de iterador e os outros conjuntos de dados no nome longo representam transformações downstream.

Por exemplo, considere o seguinte conjunto de dados de pipeline de entrada:

dataset = tf.data.Dataset.range(10).map(lambda x: x).repeat(2).batch(5)

Os nomes longos para os iteradores do conjunto de dados acima serão:

Tipo de iterador Nome longo
Variar Iterador::Lote::Repetir::Mapa::Intervalo
Mapa Iterador::Lote::Repetir::Mapa
Repetir Iterador::Lote::Repetir
Lote Iterador::Lote

Resumo de todos os pipelines de entrada

imagem

Esta seção fornece o resumo de todos os pipelines de entrada em todos os hosts. Normalmente, há um pipeline de entrada. Ao usar a estratégia de distribuição, há um pipeline de entrada do host executando o código tf.data do programa e vários pipelines de entrada do dispositivo recuperando dados do pipeline de entrada do host e transferindo-os para os dispositivos.

Para cada pipeline de entrada, ele mostra as estatísticas de seu tempo de execução. Uma chamada é considerada lenta se demorar mais de 50 μs.

Gráfico de pipeline de entrada

imagem

Esta seção mostra o gráfico do pipeline de entrada com as informações de tempo de execução. Você pode usar "Host" e "Input Pipeline" para escolher qual host e pipeline de entrada ver. As execuções do pipeline de entrada são classificadas pelo tempo de execução em ordem decrescente, que você pode escolher usando o menu suspenso Classificação .

imagem

Os nós no caminho crítico têm contornos em negrito. O nó gargalo, que é o nó com o tempo próprio mais longo no caminho crítico, tem um contorno vermelho. Os outros nós não críticos têm contornos pontilhados cinza.

Em cada nó, Start Time indica a hora de início da execução. O mesmo nó pode ser executado várias vezes, por exemplo, se houver uma operação em Batch no pipeline de entrada. Se for executado várias vezes, é a hora de início da primeira execução.

A Duração Total é o tempo de parede da execução. Se for executado várias vezes, é a soma dos tempos de parede de todas as execuções.

Self Time é o Tempo Total sem o tempo sobreposto com seus nós filhos imediatos.

"# Calls" é o número de vezes que o pipeline de entrada é executado.

Colete dados de desempenho

O TensorFlow Profiler coleta atividades de host e rastreamentos de GPU do seu modelo do TensorFlow. Você pode configurar o Profiler para coletar dados de desempenho por meio do modo programático ou do modo de amostragem.

APIs de criação de perfil

Você pode usar as seguintes APIs para realizar a criação de perfil.

  • Modo programático usando o TensorBoard Keras Callback ( tf.keras.callbacks.TensorBoard )

    # Profile from batches 10 to 15
    tb_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir,
                                                 profile_batch='10, 15')
    
    # Train the model and use the TensorBoard Keras callback to collect
    # performance profiling data
    model.fit(train_data,
              steps_per_epoch=20,
              epochs=5,
              callbacks=[tb_callback])
    
  • Modo programático usando a API de função tf.profiler

    tf.profiler.experimental.start('logdir')
    # Train the model here
    tf.profiler.experimental.stop()
    
  • Modo programático usando o gerenciador de contexto

    with tf.profiler.experimental.Profile('logdir'):
        # Train the model here
        pass
    

  • Modo de amostragem: execute a criação de perfil sob demanda usando tf.profiler.experimental.server.start para iniciar um servidor gRPC com a execução do modelo do TensorFlow. Depois de iniciar o servidor gRPC e executar seu modelo, você pode capturar um perfil por meio do botão Capturar perfil no plug-in de perfil do TensorBoard. Use o script na seção Instalar criador de perfil acima para iniciar uma instância do TensorBoard se ela ainda não estiver em execução.

    Como um exemplo,

    # Start a profiler server before your model runs.
    tf.profiler.experimental.server.start(6009)
    # (Model code goes here).
    #  Send a request to the profiler server to collect a trace of your model.
    tf.profiler.experimental.client.trace('grpc://localhost:6009',
                                          'gs://your_tb_logdir', 2000)
    

    Um exemplo de criação de perfil de vários trabalhadores:

    # E.g. your worker IP addresses are 10.0.0.2, 10.0.0.3, 10.0.0.4, and you
    # would like to profile for a duration of 2 seconds.
    tf.profiler.experimental.client.trace(
        'grpc://10.0.0.2:8466,grpc://10.0.0.3:8466,grpc://10.0.0.4:8466',
        'gs://your_tb_logdir',
        2000)
    

Use a caixa de diálogo Capture Profile para especificar:

  • Uma lista delimitada por vírgulas de URLs de serviço de perfil ou nomes de TPU.
  • Uma duração de perfil.
  • O nível de rastreamento de chamada de função de dispositivo, host e Python.
  • Quantas vezes você deseja que o Profiler tente novamente a captura de perfis se não obtiver êxito no início.

Criação de perfil de loops de treinamento personalizados

Para criar o perfil de loops de treinamento personalizados no código do TensorFlow, instrumente o loop de treinamento com a API tf.profiler.experimental.Trace para marcar os limites da etapa para o Profiler.

O argumento name é usado como um prefixo para os nomes das etapas, o argumento da palavra-chave step_num é anexado aos nomes das etapas e o argumento da palavra-chave _r faz com que esse evento de rastreamento seja processado como um evento da etapa pelo Profiler.

Como um exemplo,

for step in range(NUM_STEPS):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_data = next(dataset)
        train_step(train_data)

Isso habilitará a análise de desempenho baseada em etapas do Profiler e fará com que os eventos de etapa apareçam no visualizador de rastreamento.

Certifique-se de incluir o iterador do conjunto de dados no contexto tf.profiler.experimental.Trace para uma análise precisa do pipeline de entrada.

O trecho de código abaixo é um antipadrão:

for step, train_data in enumerate(dataset):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_step(train_data)

Casos de uso de criação de perfil

O criador de perfil abrange vários casos de uso em quatro eixos diferentes. Algumas das combinações são atualmente suportadas e outras serão adicionadas no futuro. Alguns dos casos de uso são:

  • Perfil local vs. remoto : Estas são duas maneiras comuns de configurar seu ambiente de criação de perfil. Na criação de perfil local, a API de criação de perfil é chamada na mesma máquina que seu modelo está executando, por exemplo, uma estação de trabalho local com GPUs. Na criação de perfil remota, a API de criação de perfil é chamada em uma máquina diferente de onde seu modelo está sendo executado, por exemplo, em um Cloud TPU.
  • Criação de perfil de vários trabalhadores : você pode criar o perfil de várias máquinas ao usar os recursos de treinamento distribuído do TensorFlow.
  • Plataforma de hardware : CPUs de perfil, GPUs e TPUs.

A tabela abaixo fornece uma visão geral rápida dos casos de uso compatíveis com o TensorFlow mencionados acima:

API de criação de perfil Local Controlo remoto Vários trabalhadores Plataformas de hardware
Retorno de chamada do TensorBoard Keras Compatível Não suportado Não suportado CPU, GPU
tf.profiler.experimental start/stop API Compatível Não suportado Não suportado CPU, GPU
tf.profiler.experimental client.trace API Compatível Compatível Compatível CPU, GPU, TPU
API do gerenciador de contexto Compatível Não suportado Não suportado CPU, GPU

Práticas recomendadas para o desempenho ideal do modelo

Use as recomendações a seguir conforme aplicável aos seus modelos do TensorFlow para obter o desempenho ideal.

Em geral, execute todas as transformações no dispositivo e certifique-se de usar a versão compatível mais recente de bibliotecas como cuDNN e Intel MKL para sua plataforma.

Otimize o pipeline de dados de entrada

Use os dados do [#input_pipeline_analyzer] para otimizar seu pipeline de entrada de dados. Um pipeline de entrada de dados eficiente pode melhorar drasticamente a velocidade de execução do seu modelo, reduzindo o tempo ocioso do dispositivo. Tente incorporar as práticas recomendadas detalhadas no guia Melhor desempenho com a API tf.data e abaixo para tornar seu pipeline de entrada de dados mais eficiente.

  • Em geral, paralelizar quaisquer operações que não precisem ser executadas sequencialmente pode otimizar significativamente o pipeline de entrada de dados.

  • Em muitos casos, é útil alterar a ordem de algumas chamadas ou ajustar os argumentos para que funcionem melhor para o seu modelo. Ao otimizar o pipeline de dados de entrada, avalie apenas o carregador de dados sem as etapas de treinamento e retropropagação para quantificar o efeito das otimizações de forma independente.

  • Tente executar seu modelo com dados sintéticos para verificar se o pipeline de entrada é um gargalo de desempenho.

  • Use tf.data.Dataset.shard para treinamento multi-GPU. Certifique-se de fragmentar muito cedo no loop de entrada para evitar reduções na taxa de transferência. Ao trabalhar com TFRecords, certifique-se de fragmentar a lista de TFRecords e não o conteúdo dos TFRecords.

  • Paralelize várias operações configurando dinamicamente o valor de num_parallel_calls usando tf.data.AUTOTUNE .

  • Considere limitar o uso de tf.data.Dataset.from_generator , pois ele é mais lento em comparação com as operações puras do TensorFlow.

  • Considere limitar o uso de tf.py_function , pois ele não pode ser serializado e não é compatível com a execução no TensorFlow distribuído.

  • Use tf.data.Options para controlar otimizações estáticas no pipeline de entrada.

Leia também o guia de análise de desempenho tf.data para obter mais orientações sobre como otimizar seu pipeline de entrada.

Otimize o aumento de dados

Ao trabalhar com dados de imagem, torne seu aumento de dados mais eficiente ao converter para diferentes tipos de dados após aplicar transformações espaciais, como inversão, corte, rotação etc.

Usar NVIDIA® DALI

Em alguns casos, como quando você tem um sistema com uma alta taxa de GPU para CPU, todas as otimizações acima podem não ser suficientes para eliminar gargalos no carregador de dados causados ​​por limitações de ciclos de CPU.

Se você estiver usando GPUs NVIDIA® para aplicativos de aprendizado profundo de áudio e visão computacional, considere usar a Data Loading Library ( DALI ) para acelerar o pipeline de dados.

Consulte a documentação NVIDIA® DALI: Operations para obter uma lista de operações DALI suportadas.

Use encadeamento e execução paralela

Execute operações em vários threads de CPU com a API tf.config.threading para executá-los mais rapidamente.

O TensorFlow define automaticamente o número de threads de paralelismo por padrão. O pool de threads disponível para executar as operações do TensorFlow depende do número de threads de CPU disponíveis.

Controle a aceleração paralela máxima para uma única operação usando tf.config.threading.set_intra_op_parallelism_threads . Observe que, se você executar várias operações em paralelo, todas elas compartilharão o pool de encadeamentos disponível.

Se você tiver operações independentes sem bloqueio (ops sem caminho direcionado entre elas no gráfico), use tf.config.threading.set_inter_op_parallelism_threads para executá-las simultaneamente usando o conjunto de encadeamentos disponível.

Diversos

Ao trabalhar com modelos menores em GPUs NVIDIA®, você pode definir tf.compat.v1.ConfigProto.force_gpu_compatible=True para forçar todos os tensores de CPU a serem alocados com memória CUDA fixada para aumentar significativamente o desempenho do modelo. No entanto, tenha cuidado ao usar essa opção para modelos desconhecidos/muito grandes, pois isso pode afetar negativamente o desempenho do host (CPU).

Melhore o desempenho do dispositivo

Siga as práticas recomendadas detalhadas aqui e no guia de otimização de desempenho da GPU para otimizar o desempenho do modelo TensorFlow no dispositivo.

Se você estiver usando GPUs NVIDIA, registre a GPU e a utilização de memória em um arquivo CSV executando:

nvidia-smi
--query-gpu=utilization.gpu,utilization.memory,memory.total,
memory.free,memory.used --format=csv

Configurar layout de dados

Ao trabalhar com dados que contêm informações de canal (como imagens), otimize o formato de layout de dados para preferir os canais por último (NHWC em vez de NCHW).

Os formatos de dados do último canal melhoram a utilização do Tensor Core e fornecem melhorias significativas de desempenho, especialmente em modelos convolucionais quando combinados com AMP. Os layouts de dados NCHW ainda podem ser operados por Tensor Cores, mas introduzem sobrecarga adicional devido a operações de transposição automáticas.

Você pode otimizar o layout de dados para preferir layouts NHWC configurando data_format="channels_last" para camadas como tf.keras.layers.Conv2D , tf.keras.layers.Conv3D e tf.keras.layers.RandomRotation .

Use tf.keras.backend.set_image_data_format para definir o formato de layout de dados padrão para a API de back-end Keras.

Maximize o cache L2

When working with NVIDIA® GPUs, execute the code snippet below before the training loop to max out the L2 fetch granularity to 128 bytes.

import ctypes

_libcudart = ctypes.CDLL('libcudart.so')
# Set device limit on the current device
# cudaLimitMaxL2FetchGranularity = 0x05
pValue = ctypes.cast((ctypes.c_int*1)(), ctypes.POINTER(ctypes.c_int))
_libcudart.cudaDeviceSetLimit(ctypes.c_int(0x05), ctypes.c_int(128))
_libcudart.cudaDeviceGetLimit(pValue, ctypes.c_int(0x05))
assert pValue.contents.value == 128

Configure GPU thread usage

The GPU thread mode decides how GPU threads are used.

Set the thread mode to gpu_private to make sure that preprocessing does not steal all the GPU threads. This will reduce the kernel launch delay during training. You can also set the number of threads per GPU. Set these values using environment variables.

import os

os.environ['TF_GPU_THREAD_MODE']='gpu_private'
os.environ['TF_GPU_THREAD_COUNT']='1'

Configure GPU memory options

In general, increase the batch size and scale the model to better utilize GPUs and get higher throughput. Note that increasing the batch size will change the model's accuracy so the model needs to be scaled by tuning hyperparameters like the learning rate to meet the target accuracy.

Also, use tf.config.experimental.set_memory_growth to allow GPU memory to grow to prevent all the available memory from being fully allocated to ops that require only a fraction of the memory. This allows other processes which consume GPU memory to run on the same device.

To learn more, check out the Limiting GPU memory growth guidance in the GPU guide to learn more.

Miscellaneous

  • Increase the training mini-batch size (number of training samples used per device in one iteration of the training loop) to the maximum amount that fits without an out of memory (OOM) error on the GPU. Increasing the batch size impacts the model's accuracy—so make sure you scale the model by tuning hyperparameters to meet the target accuracy.

  • Disable reporting OOM errors during tensor allocation in production code. Set report_tensor_allocations_upon_oom=False in tf.compat.v1.RunOptions .

  • For models with convolution layers, remove bias addition if using batch normalization. Batch normalization shifts values by their mean and this removes the need to have a constant bias term.

  • Use TF Stats to find out how efficiently on-device ops run.

  • Use tf.function to perform computations and optionally, enable the jit_compile=True flag ( tf.function(jit_compile=True ). To learn more, go to Use XLA tf.function .

  • Minimize host Python operations between steps and reduce callbacks. Calculate metrics every few steps instead of at every step.

  • Keep the device compute units busy.

  • Send data to multiple devices in parallel.

  • Consider using 16-bit numerical representations , such as fp16 —the half-precision floating point format specified by IEEE—or the Brain floating-point bfloat16 format.

Additional resources

Known limitations

Profiling multiple GPUs on TensorFlow 2.2 and TensorFlow 2.3

TensorFlow 2.2 and 2.3 support multiple GPU profiling for single host systems only; multiple GPU profiling for multi-host systems is not supported. To profile multi-worker GPU configurations, each worker has to be profiled independently. From TensorFlow 2.4 multiple workers can be profiled using the tf.profiler.experimental.client.trace API.

CUDA® Toolkit 10.2 or later is required to profile multiple GPUs. As TensorFlow 2.2 and 2.3 support CUDA® Toolkit versions only up to 10.1, you need to create symbolic links to libcudart.so.10.1 and libcupti.so.10.1 :

sudo ln -s /usr/local/cuda/lib64/libcudart.so.10.2 /usr/local/cuda/lib64/libcudart.so.10.1
sudo ln -s /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.2 /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.1