Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Optimización de gráficos TensorFlow con Grappler

Ver en TensorFlow.org Ejecutar en Google Colab Ver código fuente en GitHub Descargar cuaderno

Visión general

TensorFlow utiliza ejecuciones gráficas y ansiosas para ejecutar cálculos. Un tf.Graph contiene un conjunto de objetos de tf.Operation (ops) que representan unidades de cálculo y objetos tf.Tensor que representan las unidades de datos que fluyen entre operaciones.

Grappler es el sistema de optimización de gráficos predeterminado en el tiempo de ejecución de TensorFlow. Grappler aplica optimizaciones en modo gráfico (dentro de tf.function ) para mejorar el rendimiento de sus cálculos de TensorFlow a través de simplificaciones de gráficos y otras optimizaciones de alto nivel, como la incorporación de cuerpos de funciones para permitir optimizaciones entre procedimientos. La optimización de tf.Graph también reduce el uso máximo de memoria del dispositivo y mejora la utilización del hardware al optimizar el mapeo de los nodos gráficos para calcular los recursos.

Use tf.config.optimizer.set_experimental_options() para un control más tf.Graph sobre sus optimizaciones de tf.Graph .

Optimizadores gráficos disponibles

Grappler realiza optimizaciones de gráficos a través de un controlador de nivel superior llamado MetaOptimizer . Los siguientes optimizadores de gráficos están disponibles con TensorFlow:

  • Optimizador de plegado constante: infiere estáticamente el valor de los tensores cuando es posible plegando nodos constantes en el gráfico y materializa el resultado usando constantes.
  • Optimizador aritmético: simplifica las operaciones aritméticas al eliminar subexpresiones comunes y simplificar las declaraciones aritméticas.
  • Optimizador de diseño: optimiza los diseños de tensor para ejecutar operaciones dependientes del formato de datos, como las convoluciones de manera más eficiente.
  • Remapper optimizer: vuelve a mapear subgrafías en implementaciones más eficientes al reemplazar las subgrafías que ocurren comúnmente con núcleos monolíticos fusionados optimizados.
  • Optimizador de memoria: analiza el gráfico para inspeccionar el uso máximo de memoria para cada operación e inserta operaciones de copia de memoria CPU-GPU para intercambiar la memoria GPU a la CPU para reducir el uso máximo de memoria.
  • Optimizador de dependencias: elimina o reorganiza las dependencias de control para acortar la ruta crítica para un paso del modelo o permite otras optimizaciones. También elimina los nodos que efectivamente no funcionan como Identity.
  • Optimizador de poda: elimina los nodos que no tienen ningún efecto en la salida del gráfico. Por lo general, se ejecuta primero para reducir el tamaño del gráfico y acelerar el procesamiento en otras pasadas de Grappler.
  • Optimizador de funciones: optimiza la biblioteca de funciones de un programa TensorFlow e integra los cuerpos de las funciones para permitir otras optimizaciones entre procedimientos.
  • Optimizador de forma: optimiza los subgráficos que funcionan con información relacionada con la forma y la forma.
  • Optimizador autoparallel: paraleliza automáticamente los gráficos dividiéndolos a lo largo de la dimensión del lote. Este optimizador está apagado por defecto.
  • Optimizador de bucles: optimiza el flujo de control de gráficos levantando subgrafías invariantes de bucles de los bucles y eliminando las operaciones de pila redundantes en los bucles. También optimiza los bucles con recuentos de viajes conocidos estáticamente y elimina las ramas muertas estáticamente conocidas en los condicionales.
  • Optimizador de asignación de alcance : presenta los asignadores de alcance para reducir el movimiento de datos y consolidar algunas operaciones.
  • Pin to host optimizer: intercambia pequeñas operaciones en la CPU. Este optimizador está apagado por defecto.
  • Optimizador automático de precisión mixta: convierte los tipos de datos en float16 cuando corresponde para mejorar el rendimiento. Actualmente se aplica solo a las GPU.
  • Depurador de depuración: elimina los nodos relacionados con las operaciones de depuración, como tf.debugging.Assert , tf.debugging.check_numerics y tf.print del gráfico. Este optimizador está apagado por defecto.

Preparar

 import numpy as np
import timeit
import traceback
import contextlib


import tensorflow as tf
 

Cree un administrador de contexto para alternar fácilmente los estados del optimizador.

 @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 el rendimiento de ejecución con y sin Grappler

TensorFlow 2 y más allá se ejecuta ansiosamente por defecto. Use tf.function para cambiar la ejecución predeterminada al modo Gráfico. Grappler se ejecuta automáticamente en segundo plano para aplicar las optimizaciones de gráficos anteriores y mejorar el rendimiento de ejecución.

Optimizador de plegado constante

Como ejemplo preliminar, considere una función que realiza operaciones en constantes y devuelve una salida.

 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
 

Apague el optimizador de plegado constante y ejecute la función:

 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.004905937999865273 s

Habilite el optimizador de plegado constante y ejecute la función nuevamente para observar una aceleración en la ejecución de la función.

 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.0005699149999145448 s

Optimizador de depuración de stripper

Considere una función simple que verifica el valor numérico de su argumento de entrada y lo devuelve.

 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
 

Primero, ejecute la función con el optimizador de depuración eliminado.

 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 580, 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) ]]
     [[Identity/_4]]
  (1) Invalid argument:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at <ipython-input-7-cbee1561c83e>:5) ]]
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 genera un error de argumento no válido debido al argumento Inf a test_func .

Habilite el optimizador de depuración de stripper y ejecute la función nuevamente.

 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)
 

El optimizador del tf.debug.check_numerics depuración tf.debug.check_numerics nodo tf.debug.check_numerics del gráfico y ejecuta la función sin generar ningún error.

Resumen

El tiempo de ejecución de TensorFlow utiliza Grappler para optimizar los gráficos automáticamente antes de la ejecución. Use tf.config.optimizer.set_experimental_options para habilitar o deshabilitar los diversos optimizadores de gráficos.

Para obtener más información sobre Grappler, consulte Optimizaciones de gráficos de TensorFlow .