Esta página foi traduzida pela API Cloud Translation.
Switch to English

Otimização de gráfico TensorFlow com Grappler

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

Visão geral

O TensorFlow usa gráficos e execuções rápidas para executar cálculos. Um tf.Graph contém um conjunto de objetos tf.Operation (ops) que representam unidades de computação e objetos tf.Tensor que representam as unidades de dados que fluem entre as ops.

Grappler é o sistema de otimização de gráfico padrão no tempo de execução do TensorFlow. O Grappler aplica otimizações no modo gráfico (dentro de tf.function ) para melhorar o desempenho de seus cálculos do TensorFlow por meio de simplificações de gráficos e outras otimizações de alto nível, como corpos de função inlining para permitir otimizações entre procedimentos. A otimização do tf.Graph também reduz o pico de uso da memória do dispositivo e melhora a utilização do hardware otimizando o mapeamento dos nós do gráfico para computar recursos.

Use tf.config.optimizer.set_experimental_options() para um controle mais tf.Graph sobre suas otimizações tf.Graph .

Otimizadores de gráfico disponíveis

O Grappler realiza otimizações de gráfico por meio de um driver de nível superior chamado MetaOptimizer . Os seguintes otimizadores de gráfico estão disponíveis com o TensorFlow:

  • Otimizador de dobramento constante - infere estaticamente o valor dos tensores quando possível dobrando nós constantes no gráfico e materializa o resultado usando constantes.
  • Otimizador aritmético - simplifica as operações aritméticas, eliminando subexpressões comuns e simplificando as instruções aritméticas.
  • Otimizador de layout - Otimiza layouts de tensor para executar operações dependentes de formato de dados, como convoluções, com mais eficiência.
  • Otimizador de Remapeador - Remapeia os subgráficos em implementações mais eficientes, substituindo os subgráficos de ocorrência comum por kernels monolíticos fundidos otimizados.
  • Otimizador de memória - analisa o gráfico para inspecionar o pico de uso de memória para cada operação e insere operações de cópia de memória CPU-GPU para trocar a memória GPU para CPU para reduzir o pico de uso de memória.
  • Otimizador de dependência - remove ou reorganiza as dependências de controle para encurtar o caminho crítico para uma etapa do modelo ou permite outras otimizações. Também remove nós que são efetivamente autônomos, como Identidade.
  • Otimizador de poda - remove nós que não têm efeito na saída do gráfico. Geralmente é executado primeiro para reduzir o tamanho do gráfico e acelerar o processamento em outras passagens do Grappler.
  • Otimizador de funções - otimiza a biblioteca de funções de um programa TensorFlow e alinha os corpos das funções para permitir outras otimizações entre procedimentos.
  • Otimizador de formas - Otimiza subgráficos que operam em informações relacionadas a formas.
  • Otimizador autoparalelo - paralela automaticamente os gráficos dividindo ao longo da dimensão do lote. Este otimizador está DESLIGADO por padrão.
  • Otimizador de loop - Otimiza o fluxo de controle do gráfico elevando subgráficos invariantes de loop para fora dos loops e removendo operações de pilha redundantes em loops. Também otimiza loops com contagens de viagens conhecidas estaticamente e remove ramificações mortas conhecidas estaticamente em condicionais.
  • Otimizador de alocador com escopo - apresenta alocadores com escopo para reduzir a movimentação de dados e consolidar algumas operações.
  • Pin to host optimizer - Troca pequenas operações na CPU. Este otimizador está DESLIGADO por padrão.
  • Otimizador de precisão mista automática - Converte tipos de dados em float16 onde aplicável para melhorar o desempenho. Atualmente se aplica apenas a GPUs.
  • Depurador stripper - remove nós relacionados a operações de depuração, como tf.debugging.Assert , tf.debugging.check_numerics e tf.print do gráfico. Este otimizador está DESLIGADO por padrão.

Configuração

import numpy as np
import timeit
import traceback
import contextlib


import tensorflow as tf

Crie um gerenciador de contexto para alternar facilmente os estados do otimizador.

@contextlib.contextmanager
def options(options):
  old_opts = tf.config.optimizer.get_experimental_options()
  tf.config.optimizer.set_experimental_options(options)
  try:
    yield
  finally:
    tf.config.optimizer.set_experimental_options(old_opts)

Compare o desempenho de execução com e sem Grappler

O TensorFlow 2 e posteriores são executados avidamente por padrão. Use tf.function para mudar a execução padrão para o modo Graph. O Grappler é executado automaticamente em segundo plano para aplicar as otimizações de gráfico acima e melhorar o desempenho de execução.

Otimizador de dobragem constante

Como um exemplo preliminar, considere uma função que executa operações em constantes e retorna uma saída.

def test_function_1():
  @tf.function
  def simple_function(input_arg):
    print('Tracing!')
    a = tf.constant(np.random.randn(2000,2000), dtype = tf.float32)
    c = a
    for n in range(50):
      c = c@a
    return tf.reduce_mean(c+input_arg)

  return simple_function

Desligue o otimizador de dobra constante e execute a função:

with options({'constant_folding': False}):
  print(tf.config.optimizer.get_experimental_options())
  simple_function = test_function_1()
  # Trace once
  x = tf.constant(2.2)
  simple_function(x)
  print("Vanilla execution:", timeit.timeit(lambda: simple_function(x), number = 1), "s")
{'constant_folding': False, 'disable_model_pruning': False, 'disable_meta_optimizer': False}
Tracing!
Vanilla execution: 0.0801323579999007 s

Habilite o otimizador de dobra constante e execute a função novamente para observar uma aceleração na execução da função.

with options({'constant_folding': True}):
  print(tf.config.optimizer.get_experimental_options())
  simple_function = test_function_1()
  # Trace once
  x = tf.constant(2.2)
  simple_function(x)
  print("Constant folded execution:", timeit.timeit(lambda: simple_function(x), number = 1), "s")
{'constant_folding': True, 'disable_model_pruning': False, 'disable_meta_optimizer': False}
Tracing!
Constant folded execution: 0.0006300529998952697 s

Otimizador de debug stripper

Considere uma função simples que verifica o valor numérico de seu argumento de entrada e o retorna.

def test_function_2():
  @tf.function
  def simple_func(input_arg):
    output = input_arg
    tf.debugging.check_numerics(output, "Bad!")
    return output
  return simple_func

Primeiro, execute a função com o otimizador de stripper de depuração desligado.

test_func = test_function_2()
p1 = tf.constant(float('inf'))
try:
  test_func(p1)
except tf.errors.InvalidArgumentError as e:
  traceback.print_exc(limit=2)
Traceback (most recent call last):
  File "<ipython-input-8-1ac473fdfbab>", line 4, in <module>
    test_func(p1)
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/eager/def_function.py", line 780, in __call__
    result = self._call(*args, **kwds)
tensorflow.python.framework.errors_impl.InvalidArgumentError: 2 root error(s) found.
  (0) Invalid argument:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at <ipython-input-7-cbee1561c83e>:5) ]]
  (1) Invalid argument:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at <ipython-input-7-cbee1561c83e>:5) ]]
     [[Identity/_4]]
0 successful operations.
0 derived errors ignored. [Op:__inference_simple_func_131]

Errors may have originated from an input operation.
Input Source operations connected to node CheckNumerics:
 input_arg (defined at <ipython-input-8-1ac473fdfbab>:4)

Input Source operations connected to node CheckNumerics:
 input_arg (defined at <ipython-input-8-1ac473fdfbab>:4)

Function call stack:
simple_func -> simple_func


tf.debugging.check_numerics gera um erro de argumento inválido devido ao argumento Inf para test_func .

Habilite o otimizador de stripper de depuração e execute a função novamente.

with options({'debug_stripper': True}):
  test_func2 = test_function_2()
  p1 = tf.constant(float('inf'))
  try:
    test_func2(p1)
  except tf.errors.InvalidArgumentError as e:
    traceback.print_exc(limit=2)

O otimizador de stripper de depuração tf.debug.check_numericstf.debug.check_numerics do gráfico e executa a função sem gerar nenhum erro.

Resumo

O tempo de execução do TensorFlow usa Grappler para otimizar gráficos automaticamente antes da execução. Use tf.config.optimizer.set_experimental_options para ativar ou desativar os vários otimizadores de gráfico.

Para obter mais informações sobre o Grappler, consulte TensorFlow Graph Optimizations .