Home Ciencia y Tecnología Cómo usar TensorFlow Profiler para optimizar el rendimiento del modelo

Cómo usar TensorFlow Profiler para optimizar el rendimiento del modelo

44
0

Descripción normal del contenido

  • Recopilar datos de rendimiento
  • API de perfiles
  • Profiles de bucles de entrenamiento personalizados
  • Casos de uso de perfiles
  • Las mejores prácticas para un rendimiento óptimo del modelo
  • Optimizar la tubería de datos de entrada
  • Utilice la ejecución de subproceso y paralelo
  • Misceláneas
  • Mejorar el rendimiento del dispositivo
  • Recursos adicionales
  • Limitaciones conocidas
  • Perfilando múltiples GPU en TensorFlow 2.2 y TensorFlow 2.3

Recopilar datos de rendimiento

El TensorFlow Profiler recolecta actividades de host y rastros de GPU de su modelo TensorFlow. Puede configurar el Profiler para recopilar datos de rendimiento a través del modo programático o el modo de muestreo.

API de perfiles

Puede usar las siguientes API para realizar el perfil.

  • Modo programático utilizando la devolución de llamada Keras de TensorBoard (tf.keras.callbacks.TensorBoard)
# Profile from batches 10 to fifteen
tb_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir,
                                             profile_batch='10, 15')

# Practice the mannequin and use the TensorBoard Keras callback to gather
# efficiency profiling information
mannequin.match(train_data,
          steps_per_epoch=20,
          epochs=5,
          callbacks=[tb_callback])
  • Modo programático utilizando el tf.profiler API de función
tf.profiler.experimental.begin('logdir')
# Practice the mannequin right here
tf.profiler.experimental.cease()
  • Modo programático utilizando el Administrador de contexto
with tf.profiler.experimental.Profile('logdir'):
    # Practice the mannequin right here
    move

Nota: Ejecutar el Profiler durante demasiado tiempo puede hacer que se quede sin memoria. Se recomienda perfilar no más de 10 pasos a la vez. Evite perfilar los primeros lotes para evitar inexactitudes debido a la inicialización de la sobrecarga.

  • Modo de muestreo: Realice perfiles a pedido utilizando tf.profiler.experimental.server.begin Para iniciar un servidor GRPC con su modelo TensorFlow. Después de comenzar el servidor GRPC y ejecutar su modelo, puede capturar un perfil a través del Perfil de captura Botón en el complemento de perfil de Tensorboard. Use el script en la sección Instalar Profiler anterior para iniciar una instancia de TensorBoard si aún no se está ejecutando.

    Como ejemplo,

# Begin a profiler server earlier than your mannequin runs.
tf.profiler.experimental.server.begin(6009)
# (Mannequin code goes right here).
#  Ship a request to the profiler server to gather a hint of your mannequin.
tf.profiler.experimental.consumer.hint('grpc://localhost:6009',
                                      'gs://your_tb_logdir', 2000)

Un ejemplo para perfilar múltiples trabajadores:

# E.g., your employee IP addresses are 10.0.0.2, 10.0.0.3, 10.0.0.4, and also you
# wish to profile for a period of two seconds.
tf.profiler.experimental.consumer.hint(
    'grpc://10.0.0.2:8466,grpc://10.0.0.3:8466,grpc://10.0.0.4:8466',
    'gs://your_tb_logdir',
    2000)

Usar el Perfil de captura diálogo para especificar:

  • Una lista de servicio de comas de URL de servicio de perfil o nombres de TPU.
  • Una duración de perfil.
  • El nivel de la función de dispositivo, host y pitón llaman al rastreo de llamadas.
  • Cuántas veces desea que el Profiler vuelva a intentar la captura de perfiles si no tiene éxito al principio.

Profiles de bucles de entrenamiento personalizados

Para perfilar bucles de entrenamiento personalizados en su código TensorFlow, instrumenten el bucle de entrenamiento con el tf.profiler.experimental.Hint API para marcar los límites de paso para el Profiler.

El title El argumento se usa como prefijo para los nombres de pasos, el step_num El argumento de palabras clave se adjunta en los nombres de pasos y en el _r El argumento de palabras clave hace que este evento traza se procese como un evento de paso por el Profiler.

Como ejemplo,

for step in vary(NUM_STEPS):
    with tf.profiler.experimental.Hint('practice', step_num=step, _r=1):
        train_data = subsequent(dataset)
        train_step(train_data)

Esto permitirá el análisis de rendimiento basado en escalones del Profiler y causará que aparezcan los eventos de paso en el Visor de Hint.

Asegúrese de incluir el iterador del conjunto de datos dentro del tf.profiler.experimental.Hint Contexto para un análisis preciso de la tubería de entrada.

El fragmento de código a continuación es un antipatrón:

Advertencia: Esto dará como resultado un análisis inexacto de la tubería de entrada.

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

Casos de uso de perfiles

El Profiler cubre una serie de casos de uso a lo largo de cuatro ejes diferentes. Algunas de las combinaciones son compatibles actualmente y otras se agregarán en el futuro. Algunos de los casos de uso son:

  • Perfiles locales vs. remoto: Estas son dos formas comunes de configurar su entorno de perfil. En el perfil native, la API de perfiles se llama en la misma máquina que su modelo está ejecutando, por ejemplo, una estación de trabajo native con GPU. En el perfil remoto, la API de perfiles se llama en una máquina diferente de donde su modelo se está ejecutando, por ejemplo, en una TPU en la nube.
  • Perfilando múltiples trabajadores: Puede perfilar varias máquinas cuando use las capacidades de entrenamiento distribuidas de TensorFlow.
  • Plataforma de {hardware}: CPU de perfil, GPU y TPU.

La siguiente tabla proporciona una visión normal rápida de los casos de uso soportados por TensorFlow mencionados anteriormente:

API de perfiles

Native

Remoto

Múltiples trabajadores

Plataformas de {hardware}

Tensorboard keras devolución de llamada

Suitable

No suitable

No suitable

CPU, GPU

tf.profiler.experimental API de inicio/parada

Suitable

No suitable

No suitable

CPU, GPU

tf.profiler.experimental Consumer. Hint API

Suitable

Suitable

Suitable

CPU, GPU, TPU

API del gerente de contexto

Suitable

No suitable

No suitable

CPU, GPU

Las mejores prácticas para un rendimiento óptimo del modelo

Use las siguientes recomendaciones que corresponda para sus modelos TensorFlow para lograr un rendimiento óptimo.

En normal, realice todas las transformaciones en el dispositivo y asegúrese de utilizar la última versión suitable de bibliotecas como CUDNN e Intel MKL para su plataforma.

Optimizar la tubería de datos de entrada

Use los datos del [#input_pipeline_analyzer] Para optimizar su tubería de entrada de datos. Una canalización de entrada de datos eficiente puede mejorar drásticamente la velocidad de la ejecución de su modelo reduciendo el tiempo de inactividad del dispositivo. Intente incorporar las mejores prácticas detalladas en el mejor rendimiento con la Guía de la API TF.DATA y a continuación para que su tubería de entrada de datos sea más eficiente.

  • En normal, la paralelización de cualquier OPS que no sea necesario ejecutar secuencialmente puede optimizar significativamente la tubería de entrada de datos.
  • En muchos casos, ayuda a cambiar el orden de algunas llamadas o sintonizar los argumentos de tal manera que funcione mejor para su modelo. Mientras optimiza la tubería de datos de entrada, evaluate solo el cargador de datos sin los pasos de entrenamiento y respaldo para cuantificar el efecto de las optimizaciones de forma independiente.
  • Intente ejecutar su modelo con datos sintéticos para verificar si la tubería de entrada es un cuello de botella de rendimiento.
  • Usar tf.information.Dataset.shard para entrenamiento multi-GPU. Asegúrese de fragmentar muy temprano en el bucle de entrada para evitar reducciones en el rendimiento. Cuando trabaje con TFRecords, asegúrese de fragmentar la lista de TFRecords y no el contenido de los TFRecords.
  • Paralelizar varios OP estableciendo dinámicamente el valor de num_parallel_calls usando tf.information.AUTOTUNE.
  • Considere limitar el uso de tf.information.Dataset.from_generator ya que es más lento en comparación con los OP de flujo de tensor puro.
  • Considere limitar el uso de tf.py_function ya que no se puede serializar y no es suitable con la ejecución en TensorFlow distribuido.
  • Usar tf.information.Choices Para controlar las optimizaciones estáticas a la tubería de entrada.

También lee el tf.information Guía de análisis de rendimiento para obtener más orientación sobre la optimización de su tubería de entrada.

Optimizar el aumento de datos

Cuando trabaje con datos de imagen, haga que su aumento de datos sea más eficiente al fundar a diferentes tipos de datos después Aplicar transformaciones espaciales, como voltear, recortar, girar, and so forth.

Nota: Algunas operaciones como tf.picture.resize cambiar transparentemente el dtype a fp32. Asegúrese de normalizar sus datos para mentir entre 0 y 1 Si no se hace automáticamente. Saltar este paso podría conducir a NaN Errores si tiene habilitado AMPERIO.

Use NVIDIA® Dali

En algunos casos, como cuando tiene un sistema con una alta relación GPU a CPU, todas las optimizaciones anteriores pueden no ser suficientes para eliminar los cuellos de botella en el cargador de datos causados por limitaciones de los ciclos de CPU.

Si está utilizando las GPU NVIDIA® para aplicaciones de visión por computadora y aprendizaje profundo de audio, considere usar la Biblioteca de carga de datos (DALI) para acelerar la tubería de datos.

Consulte la documentación de NVIDIA® Dali: operaciones para obtener una lista de OPS DALI compatibles.

Utilice la ejecución de subproceso y paralelo

Ejecute OPS en múltiples hilos de CPU con el tf.config.threading API para ejecutarlos más rápido.

TensorFlow establece automáticamente el número de hilos de paralelismo de forma predeterminada. El grupo de subprocesos disponibles para ejecutar OPS TensorFlow depende de la cantidad de hilos de CPU disponibles.

Controlar la aceleración paralela máxima para un solo OP utilizando tf.config.threading.set_intra_op_parallelism_threads. Tenga en cuenta que si ejecuta múltiples OPS en paralelo, todos compartirán el grupo de subprocesos disponible.

Si tiene OPS sin bloqueo independiente (OPS sin ruta dirigida entre ellos en el gráfico), use tf.config.threading.set_inter_op_parallelism_threads para ejecutarlos simultáneamente usando el grupo de subprocesos disponible.

Misceláneas

Al trabajar con modelos más pequeños en las GPU de NVIDIA®, puede establecer tf.compat.v1.ConfigProto.force_gpu_compatible=True Para obligar a todos los tensores de la CPU a asignarse con la memoria cubierta de CUDA para dar un impulso significativo al rendimiento del modelo. Sin embargo, ejercer precaución mientras usa esta opción para modelos desconocidos/muy grandes, ya que esto podría afectar negativamente el rendimiento del host (CPU).

Mejorar el rendimiento del dispositivo

Siga las mejores prácticas detalladas aquí y en la Guía de optimización de rendimiento de la GPU para optimizar el rendimiento del modelo de flujo de tensor en el dispositivo.

Si está utilizando las GPU NVIDIA, registre la utilización de GPU y memoria en un archivo CSV ejecutando:

nvidia-smi
--query-gpu=utilization.gpu,utilization.reminiscence,reminiscence.whole,
reminiscence.free,reminiscence.used --format=csv

Configurar el diseño de datos

Cuando trabaje con datos que contienen información del canal (como imágenes), optimice el formato de diseño de datos para preferir los canales al closing (NHWC sobre NCHW).

Los formatos de datos del canal mejoran la utilización del núcleo del tensor y proporcionan mejoras de rendimiento significativas, especialmente en modelos convolucionales cuando se acoplan con AMP. Los diseños de datos NCHW aún pueden ser operados por núcleos de tensor, pero introducen sobrecargas adicionales debido a OPS de transposición automática.

Puede optimizar el diseño de datos para preferir los diseños NHWC configurando data_format="channels_last" para capas como tf.keras.layers.Conv2D, tf.keras.layers.Conv3Dy tf.keras.layers.RandomRotation.

Usar tf.keras.backend.set_image_data_format Para establecer el formato de diseño de datos predeterminado para la API de backend Keras.

Max out el caché L2

Cuando trabaje con las GPU NVIDIA®, ejecute el fragmento de código a continuación antes del circuito de entrenamiento para maximizar la granularidad de L2 Fetch a 128 bytes.

import ctypes

_libcudart = ctypes.CDLL('libcudart.so')
# Set system restrict on the present system
# cudaLimitMaxL2FetchGranularity = 0x05
pValue = ctypes.solid((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.worth == 128

Configurar el uso del hilo de GPU

El modo de hilo GPU determine cómo se utilizan los hilos de GPU.

Establezca el modo de subproceso en gpu_private Para asegurarse de que el preprocesamiento no gown todos los hilos de la GPU. Esto reducirá el retraso de lanzamiento del núcleo durante el entrenamiento. También puede establecer el número de hilos por GPU. Establezca estos valores utilizando variables de entorno.

import os

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

Configurar opciones de memoria de GPU

En normal, aumente el tamaño del lote y escala el modelo para utilizar mejor las GPU y obtener un mayor rendimiento. Tenga en cuenta que aumentar el tamaño del lote cambiará la precisión del modelo, por lo que el modelo debe escalarse ajustando hiperparámetros como la tasa de aprendizaje para cumplir con la precisión del objetivo.

Además, usa tf.config.experimental.set_memory_growth Para permitir que la memoria de GPU crezca para evitar que toda la memoria disponible se asigne completamente a OPS que solo requieren una fracción de la memoria. Esto permite que otros procesos que consumen memoria GPU se ejecuten en el mismo dispositivo.

Para obtener más información, consulte la guía limitante de crecimiento de la memoria de la GPU en la Guía de GPU para obtener más información.

Misceláneas

  • Aumente el tamaño de mini lote de entrenamiento (número de muestras de entrenamiento utilizadas por dispositivo en una iteración del bucle de entrenamiento) a la cantidad máxima que se ajusta sin un error fuera de memoria (OOM) en la GPU. El aumento del tamaño del lote impacta la precisión del modelo, así que asegúrese de escalar el modelo ajustando los hiperparámetros para cumplir con la precisión del objetivo.
  • Desactivar informes de errores OOM durante la asignación de tensor en el código de producción. Colocar report_tensor_allocations_upon_oom=False en tf.compat.v1.RunOptions.
  • Para modelos con capas de convolución, elimine la adición de sesgo si usa la normalización por lotes. La normalización por lotes cambia los valores por su media y esto elimina la necesidad de tener un término de sesgo constante.
  • Use estadísticas de TF para averiguar qué tan eficientemente se ejecutan OPS en el dispositivo.
  • Usar tf.perform Para realizar cálculos y opcionalmente, habilite el jit_compile=True bandera (tf.perform(jit_compile=True). Para obtener más información, vaya a usar XLA TF.Perform.
  • Minimice las operaciones del host Python entre los pasos y reduzca las devoluciones de llamada. Calcule las métricas cada pocos pasos en lugar de en cada paso.
  • Mantenga las unidades de cómputo del dispositivo ocupadas.
  • Envíe datos a múltiples dispositivos en paralelo.
  • Considere usar representaciones numéricas de 16 bits, como fp16—El formato de punto flotante de media precisión especificado por IEEE, o el formato BFLOAT16 de punto flotante cerebral.

Recursos adicionales

Limitaciones conocidas

Perfilando múltiples GPU en TensorFlow 2.2 y TensorFlow 2.3

TensorFlow 2.2 y 2.3 admiten múltiples perfiles de GPU solo para sistemas de host único; No es suitable con múltiples perfiles de GPU para sistemas de múltiples huéspedes. Para perfilar configuraciones de GPU múltiples, cada trabajador debe ser perfilado de forma independiente. De tensorflow 2.4 múltiples trabajadores pueden ser perfilados utilizando el tf.profiler.experimental.consumer.hint API.

Se requiere CUDA® Toolkit 10.2 o posterior para perfilar múltiples GPU. Como TensorFlow 2.2 y 2.3 admiten versiones de equipment de herramientas CUDA® solo hasta 10.1, debe crear enlaces simbólicos a libcudart.so.10.1 y libcupti.so.10.1:

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

Publicado originalmente en el Flujo tensor Sitio net, este artículo aparece aquí en un nuevo titular y tiene licencia bajo CC por 4.0. Muestras de código compartidas bajo la licencia Apache 2.0.

fuente