Optimización de gráficos de TensorFlow con Grappler

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar libreta

Descripción general

TensorFlow usa ejecuciones gráficas y ansiosas para ejecutar cálculos. Un tf.Graph contiene un conjunto de objetos 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 los 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 mediante la optimización de la asignación de nodos de gráficos a los recursos informáticos.

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

Optimizadores de 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 al plegar nodos constantes en el gráfico y materializa el resultado usando constantes.
  • Optimizador aritmético: simplifica las operaciones aritméticas eliminando las subexpresiones comunes y simplificando las declaraciones aritméticas.
  • Optimizador de diseño: optimiza los diseños de tensor para ejecutar operaciones dependientes del formato de datos, como circunvoluciones, de manera más eficiente.
  • Optimizador de reasignación: reasigna subgráficos en implementaciones más eficientes al reemplazar los subgráficos 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 memoria GPU por 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 de un paso del modelo o permite otras optimizaciones. También elimina los nodos que efectivamente no son operativos, como Identidad.
  • 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 otros pases de Grappler.
  • Optimizador de funciones: optimiza la biblioteca de funciones de un programa TensorFlow y los cuerpos de funciones en línea para habilitar otras optimizaciones entre procedimientos.
  • Optimizador de forma: optimiza los subgráficos que operan en la forma y la información relacionada con la forma.
  • Optimizador autoparalelo: paraleliza automáticamente los gráficos dividiéndolos a lo largo de la dimensión del lote. Este optimizador está desactivado de forma predeterminada.
  • Optimizador de bucles: optimiza el flujo de control de gráficos elevando los subgráficos invariantes de bucles fuera 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 ramas muertas conocidas estáticamente en condicionales.
  • Optimizador de asignadores de alcance: presenta asignadores de alcance para reducir el movimiento de datos y consolidar algunas operaciones.
  • Anclar al optimizador de host: intercambia pequeñas operaciones en la CPU. Este optimizador está desactivado de forma predeterminada.
  • Optimizador de precisión mixto automático: convierte los tipos de datos a float16 cuando corresponda para mejorar el rendimiento. Actualmente solo se aplica a las GPU.
  • Eliminador 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á desactivado de forma predeterminada.

Configuración

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 posteriores se ejecutan con entusiasmo de forma predeterminada. 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.0018392090000816097 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.0006749789999958011 s

Optimizador de eliminación de errores

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 eliminación de errores desactivado.

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)
2021-09-22 20:34:55.871238: E tensorflow/core/kernels/check_numerics_op.cc:292] abnormal_detected_host @0x7f4878e00100 = {0, 1} Bad!
Traceback (most recent call last):
  File "/tmp/ipykernel_22954/3616845043.py", line 4, in <module>
    test_func(p1)
  File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 885, in __call__
    result = self._call(*args, **kwds)
tensorflow.python.framework.errors_impl.InvalidArgumentError:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at tmp/ipykernel_22954/2241890286.py:5) ]] [Op:__inference_simple_func_131]

Errors may have originated from an input operation.
Input Source operations connected to node CheckNumerics:
 input_arg (defined at tmp/ipykernel_22954/3616845043.py:4)

Function call stack:
simple_func

tf.debugging.check_numerics genera un error de argumento no válido debido al argumento Inf para test_func .

Habilite el optimizador de eliminación de errores 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 de eliminación de errores elimina el 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 usa 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 .