Optimice el rendimiento de TensorFlow usando Profiler

Esta guía demuestra cómo utilizar las herramientas disponibles con TensorFlow Profiler para realizar un seguimiento del rendimiento de sus modelos de TensorFlow. Aprenderá a comprender el rendimiento de su modelo en el host (CPU), el dispositivo (GPU) o en una combinación de host y dispositivo(s).

La creación de perfiles ayuda a comprender el consumo de recursos de hardware (tiempo y memoria) de las diversas operaciones (ops) de TensorFlow en su modelo y resuelve los cuellos de botella de rendimiento y, en última instancia, hace que el modelo se ejecute más rápido.

Esta guía lo guiará a través de cómo instalar Profiler, las diversas herramientas disponibles, los diferentes modos de cómo Profiler recopila datos de rendimiento y algunas mejores prácticas recomendadas para optimizar el rendimiento del modelo.

Si desea perfilar el rendimiento de su modelo en Cloud TPU, consulte la guía de Cloud TPU .

Instale los requisitos previos de Profiler y GPU

Instale el complemento Profiler para TensorBoard con pip. Tenga en cuenta que Profiler requiere las últimas versiones de TensorFlow y TensorBoard (>=2.2).

pip install -U tensorboard_plugin_profile

Para perfilar en la GPU, debe:

  1. Cumpla con los controladores de GPU NVIDIA® y los requisitos del kit de herramientas CUDA® enumerados en los requisitos de software de soporte de GPU de TensorFlow .
  2. Asegúrese de que la interfaz de herramientas de generación de perfiles NVIDIA® CUDA® (CUPTI) exista en la ruta:

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

Si no tiene CUPTI en la ruta, anteponga su directorio de instalación a la variable de entorno $LD_LIBRARY_PATH ejecutando:

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

Luego, ejecute el comando ldconfig anterior nuevamente para verificar que se encuentra la biblioteca CUPTI.

Resolver problemas de privilegios

Cuando ejecuta la generación de perfiles con CUDA® Toolkit en un entorno Docker o en Linux, puede encontrar problemas relacionados con privilegios CUPTI insuficientes ( CUPTI_ERROR_INSUFFICIENT_PRIVILEGES ). Vaya a los Documentos para desarrolladores de NVIDIA para obtener más información sobre cómo puede resolver estos problemas en Linux.

Para resolver problemas de privilegios CUPTI en un entorno Docker, ejecute

docker run option '--privileged=true'

Herramientas del generador de perfiles

Acceda al generador de perfiles desde la pestaña Perfil en TensorBoard, que aparece solo después de haber capturado algunos datos del modelo.

Profiler tiene una selección de herramientas para ayudar con el análisis de rendimiento:

  • Página de descripción general
  • Analizador de canalización de entrada
  • Estadísticas de TensorFlow
  • Visor de seguimiento
  • Estadísticas del núcleo de la GPU
  • Herramienta de perfil de memoria
  • Visor de pods

Página de descripción general

La página de descripción general proporciona una vista de nivel superior del rendimiento de su modelo durante la ejecución de un perfil. La página le muestra una página de descripción general agregada para su host y todos los dispositivos, y algunas recomendaciones para mejorar el rendimiento de la capacitación de su modelo. También puede seleccionar hosts individuales en el menú desplegable Host.

La página de resumen muestra los datos de la siguiente manera:

imagen

  • Resumen de rendimiento : muestra un resumen de alto nivel del rendimiento de su modelo. El resumen de rendimiento consta de dos partes:

    1. Desglose de tiempo de paso: desglosa el tiempo de paso promedio en múltiples categorías de dónde se gasta el tiempo:

      • Compilación: tiempo dedicado a compilar núcleos.
      • Entrada: Tiempo dedicado a leer los datos de entrada.
      • Salida: tiempo dedicado a leer los datos de salida.
      • Lanzamiento del kernel: tiempo que dedica el host a lanzar los kernels
      • Tiempo de cómputo del host..
      • Tiempo de comunicación de dispositivo a dispositivo.
      • Tiempo de cómputo en el dispositivo.
      • Todos los demás, incluida la sobrecarga de Python.
    2. Precisiones de cómputo del dispositivo: informa el porcentaje de tiempo de cómputo del dispositivo que usa cómputos de 16 y 32 bits.

  • Gráfico de tiempo de paso : muestra un gráfico del tiempo de paso del dispositivo (en milisegundos) sobre todos los pasos muestreados. Cada paso se divide en múltiples categorías (con diferentes colores) de dónde se gasta el tiempo. El área roja corresponde a la parte del tiempo de paso que los dispositivos estuvieron inactivos esperando datos de entrada del host. El área verde muestra cuánto tiempo estuvo funcionando realmente el dispositivo.

  • Las 10 principales operaciones de TensorFlow en el dispositivo (por ejemplo, GPU) : muestra las operaciones en el dispositivo que se ejecutaron durante más tiempo.

    Cada fila muestra el tiempo propio de una operación (como el porcentaje de tiempo empleado por todas las operaciones), el tiempo acumulado, la categoría y el nombre.

  • Entorno de ejecución : muestra un resumen de alto nivel del entorno de ejecución del modelo, que incluye:

    • Número de hosts utilizados.
    • Tipo de dispositivo (GPU/TPU).
    • Número de núcleos del dispositivo.
  • Recomendación para el siguiente paso : informa cuando un modelo está vinculado a la entrada y recomienda herramientas que puede usar para localizar y resolver cuellos de botella en el rendimiento del modelo.

Analizador de tubería de entrada

Cuando un programa de TensorFlow lee datos de un archivo, comienza en la parte superior del gráfico de TensorFlow de manera canalizada. El proceso de lectura se divide en varias etapas de procesamiento de datos conectadas en serie, donde la salida de una etapa es la entrada de la siguiente. Este sistema de lectura de datos se denomina tubería de entrada .

Una tubería típica para leer registros de archivos tiene las siguientes etapas:

  1. Lectura de archivos.
  2. Preprocesamiento de archivos (opcional).
  3. Transferencia de archivos del host al dispositivo.

Una canalización de entrada ineficiente puede ralentizar gravemente su aplicación. Una aplicación se considera vinculada a la entrada cuando pasa una parte significativa del tiempo en la canalización de entrada. Utilice la información obtenida del analizador de canalización de entrada para comprender dónde la canalización de entrada es ineficiente.

El analizador de canalización de entrada le indica de inmediato si su programa está vinculado a la entrada y lo guía a través del análisis del lado del dispositivo y del host para depurar cuellos de botella de rendimiento en cualquier etapa de la canalización de entrada.

Consulte la guía sobre el rendimiento de la canalización de entrada para conocer las mejores prácticas recomendadas para optimizar sus canalizaciones de entrada de datos.

Panel de canalización de entrada

Para abrir el analizador de canalización de entrada, seleccione Perfil y, a continuación, seleccione input_pipeline_analyzer en el menú desplegable Herramientas .

imagen

El tablero contiene tres secciones:

  1. Resumen : Resume la canalización de entrada general con información sobre si su aplicación está vinculada a la entrada y, de ser así, en qué medida.
  2. Análisis del lado del dispositivo : muestra resultados detallados del análisis del lado del dispositivo, incluido el tiempo de paso del dispositivo y el rango de tiempo del dispositivo que se pasó esperando los datos de entrada en los núcleos en cada paso.
  3. Análisis del lado del host : muestra un análisis detallado del lado del host, incluido un desglose del tiempo de procesamiento de entrada en el host.

Resumen de canalización de entrada

El resumen informa si su programa está vinculado a la entrada al presentar el porcentaje de tiempo del dispositivo que se dedica a esperar la entrada del host. Si está utilizando una canalización de entrada estándar que ha sido instrumentada, la herramienta informa dónde se gasta la mayor parte del tiempo de procesamiento de entrada.

Análisis del lado del dispositivo

El análisis del lado del dispositivo proporciona información sobre el tiempo pasado en el dispositivo en comparación con el host y cuánto tiempo del dispositivo se dedicó a esperar los datos de entrada del host.

  1. Tiempo de paso trazado contra el número de paso : Muestra un gráfico del tiempo de paso del dispositivo (en milisegundos) sobre todos los pasos muestreados. Cada paso se divide en múltiples categorías (con diferentes colores) de dónde se gasta el tiempo. El área roja corresponde a la parte del tiempo de paso que los dispositivos estuvieron inactivos esperando datos de entrada del host. El área verde muestra cuánto tiempo estuvo funcionando realmente el dispositivo.
  2. Estadísticas de tiempo de paso : informa el promedio, la desviación estándar y el rango ([mínimo, máximo]) del tiempo de paso del dispositivo.

Análisis del lado del anfitrión

El análisis del lado del host informa un desglose del tiempo de procesamiento de entrada (el tiempo dedicado a las operaciones de la API de tf.data ) en el host en varias categorías:

  • Lectura de datos de archivos bajo demanda : tiempo dedicado a la lectura de datos de archivos sin almacenamiento en caché, captura previa e intercalado.
  • Lectura de datos de archivos por adelantado : tiempo dedicado a la lectura de archivos, incluido el almacenamiento en caché, la captación previa y el intercalado.
  • Preprocesamiento de datos : tiempo dedicado a operaciones de preprocesamiento, como la descompresión de imágenes.
  • Poner en cola los datos para transferirlos al dispositivo : el tiempo dedicado a poner los datos en una cola de alimentación antes de transferirlos al dispositivo.

Expanda Estadísticas de operaciones de entrada para inspeccionar las estadísticas de operaciones de entrada individuales y sus categorías desglosadas por tiempo de ejecución.

imagen

Aparecerá una tabla de datos de origen con cada entrada que contiene la siguiente información:

  1. Op. de entrada : muestra el nombre de la operación de TensorFlow de la operación de entrada.
  2. Recuento : muestra el número total de instancias de ejecución de operaciones durante el período de generación de perfiles.
  3. Tiempo total (en ms) : muestra la suma acumulada del tiempo dedicado a cada una de esas instancias.
  4. % de tiempo total : muestra el tiempo total dedicado a una operación como una fracción del tiempo total dedicado al procesamiento de entrada.
  5. Tiempo total propio (en ms) : muestra la suma acumulada del tiempo propio dedicado a cada una de esas instancias. El tiempo propio aquí mide el tiempo pasado dentro del cuerpo de la función, excluyendo el tiempo pasado en la función a la que llama.
  6. % de tiempo propio total . Muestra el tiempo total propio como una fracción del tiempo total dedicado al procesamiento de entrada.
  7. categoría Muestra la categoría de procesamiento de la operación de entrada.

Estadísticas de TensorFlow

La herramienta TensorFlow Stats muestra el rendimiento de cada operación de TensorFlow que se ejecuta en el host o dispositivo durante una sesión de generación de perfiles.

imagen

La herramienta muestra información de rendimiento en dos paneles:

  • El panel superior muestra hasta cuatro gráficos circulares:

    1. La distribución del tiempo de autoejecución de cada operación en el host.
    2. La distribución del tiempo de autoejecución de cada tipo de operación en el host.
    3. La distribución del tiempo de autoejecución de cada operación en el dispositivo.
    4. La distribución del tiempo de autoejecución de cada tipo de operación en el dispositivo.
  • El panel inferior muestra una tabla que informa datos sobre las operaciones de TensorFlow con una fila para cada operación y una columna para cada tipo de datos (ordene las columnas haciendo clic en el encabezado de la columna). Haga clic en el botón Exportar como CSV en el lado derecho del panel superior para exportar los datos de esta tabla como un archivo CSV.

    Tenga en cuenta que:

    • Si alguna operación tiene operaciones secundarias:

      • El tiempo total "acumulado" de una operación incluye el tiempo pasado dentro de las operaciones secundarias.
      • El tiempo "auto" total de una operación no incluye el tiempo pasado dentro de las operaciones secundarias.
    • Si una operación se ejecuta en el host:

      • El porcentaje del tiempo propio total en el dispositivo incurrido por la opción será 0.
      • El porcentaje acumulativo del tiempo propio total en el dispositivo hasta esta operación incluida será 0.
    • Si una operación se ejecuta en el dispositivo:

      • El porcentaje del tiempo libre total en el host incurrido por esta operación será 0.
      • El porcentaje acumulativo del tiempo propio total en el host hasta esta operación incluida será 0.

Puede optar por incluir o excluir el tiempo de inactividad en los gráficos circulares y la tabla.

Visor de seguimiento

El visor de seguimiento muestra una línea de tiempo que muestra:

  • Duraciones de las operaciones que ejecutó su modelo de TensorFlow
  • Qué parte del sistema (host o dispositivo) ejecutó una operación. Por lo general, el host ejecuta operaciones de entrada, preprocesa los datos de entrenamiento y los transfiere al dispositivo, mientras que el dispositivo ejecuta el entrenamiento del modelo real.

El visor de seguimiento le permite identificar problemas de rendimiento en su modelo y luego tomar medidas para resolverlos. Por ejemplo, en un nivel alto, puede identificar si el entrenamiento de entrada o de modelo está ocupando la mayor parte del tiempo. Profundizando, puede identificar qué operaciones tardan más en ejecutarse. Tenga en cuenta que el visor de seguimiento está limitado a 1 millón de eventos por dispositivo.

Interfaz del visor de seguimiento

Cuando abre el visor de seguimiento, aparece mostrando su ejecución más reciente:

imagen

Esta pantalla contiene los siguientes elementos principales:

  1. Panel de línea de tiempo: muestra las operaciones que el dispositivo y el host ejecutaron a lo largo del tiempo.
  2. Panel de detalles : muestra información adicional para las operaciones seleccionadas en el panel Línea de tiempo.

El panel Línea de tiempo contiene los siguientes elementos:

  1. Barra superior : Contiene varios controles auxiliares.
  2. Eje de tiempo : Muestra el tiempo relativo al comienzo de la traza.
  3. Etiquetas de sección y pista : cada sección contiene varias pistas y tiene un triángulo a la izquierda en el que puede hacer clic para expandir y contraer la sección. Hay una sección para cada elemento de procesamiento en el sistema.
  4. Selector de herramientas : contiene varias herramientas para interactuar con el visor de seguimiento, como Zoom, Pan, Select y Timing. Utilice la herramienta Tiempo para marcar un intervalo de tiempo.
  5. Eventos : muestran el tiempo durante el cual se ejecutó una operación o la duración de los metaeventos, como los pasos de entrenamiento.
Secciones y pistas

El visor de seguimiento contiene las siguientes secciones:

  • Una sección para cada nodo de dispositivo , etiquetada con el número del chip del dispositivo y el nodo del dispositivo dentro del chip (por ejemplo, /device:GPU:0 (pid 0) ). Cada sección de nodo de dispositivo contiene las siguientes pistas:
    • Paso : muestra la duración de los pasos de entrenamiento que se estaban ejecutando en el dispositivo
    • TensorFlow Ops : muestra las operaciones ejecutadas en el dispositivo
    • XLA Ops : muestra las operaciones XLA (ops) que se ejecutaron en el dispositivo si XLA es el compilador utilizado (cada operación TensorFlow se traduce en una o varias operaciones XLA. El compilador XLA traduce las operaciones XLA en código que se ejecuta en el dispositivo).
  • Una sección para subprocesos que se ejecutan en la CPU de la máquina host, denominada "Subprocesos de host" . La sección contiene una pista para cada subproceso de la CPU. Tenga en cuenta que puede ignorar la información que se muestra junto a las etiquetas de las secciones.
Eventos

Los eventos dentro de la línea de tiempo se muestran en diferentes colores; los colores en sí no tienen un significado específico.

El visor de seguimiento también puede mostrar seguimientos de llamadas a funciones de Python en su programa TensorFlow. Si usa la API tf.profiler.experimental.start , puede habilitar el seguimiento de Python usando ProfilerOptions namedtuple al iniciar la generación de perfiles. De forma alternativa, si utiliza el modo de muestreo para la creación de perfiles, puede seleccionar el nivel de rastreo utilizando las opciones desplegables en el cuadro de diálogo Capturar perfil .

imagen

Estadísticas del núcleo GPU

Esta herramienta muestra estadísticas de rendimiento y la operación de origen para cada kernel acelerado por GPU.

imagen

La herramienta muestra información en dos paneles:

  • El panel superior muestra un gráfico circular que muestra los núcleos CUDA que tienen el tiempo total transcurrido más alto.

  • El panel inferior muestra una tabla con los siguientes datos para cada par kernel-op único:

    • Una clasificación en orden descendente de la duración total de GPU transcurrida agrupada por par kernel-op.
    • El nombre del kernel lanzado.
    • El número de registros de GPU utilizados por el kernel.
    • El tamaño total de la memoria compartida (estática + dinámica compartida) utilizada en bytes.
    • La dimensión del bloque expresada como blockDim.x, blockDim.y, blockDim.z .
    • Las dimensiones de la cuadrícula expresadas como gridDim.x, gridDim.y, gridDim.z .
    • Si la operación es elegible para usar Tensor Cores .
    • Si el kernel contiene instrucciones de Tensor Core.
    • El nombre de la operación que lanzó este kernel.
    • El número de ocurrencias de este par kernel-op.
    • El tiempo de GPU total transcurrido en microsegundos.
    • El tiempo promedio de GPU transcurrido en microsegundos.
    • El tiempo de GPU mínimo transcurrido en microsegundos.
    • El tiempo de GPU máximo transcurrido en microsegundos.

Herramienta de perfil de memoria

La herramienta Perfil de memoria supervisa el uso de la memoria de su dispositivo durante el intervalo de creación de perfiles. Puede utilizar esta herramienta para:

  • Depure los problemas de falta de memoria (OOM) identificando el uso máximo de memoria y la asignación de memoria correspondiente a las operaciones de TensorFlow. También puede depurar los problemas de OOM que pueden surgir cuando ejecuta la inferencia de múltiples inquilinos .
  • Depurar problemas de fragmentación de memoria.

La herramienta de perfil de memoria muestra datos en tres secciones:

  1. Resumen del perfil de memoria
  2. Gráfico de línea de tiempo de memoria
  3. Tabla de desglose de memoria

Resumen del perfil de memoria

Esta sección muestra un resumen de alto nivel del perfil de memoria de su programa TensorFlow como se muestra a continuación:

El resumen del perfil de memoria tiene seis campos:

  1. ID de memoria : menú desplegable que enumera todos los sistemas de memoria del dispositivo disponibles. Seleccione el sistema de memoria que desea ver en el menú desplegable.
  2. #Allocation : el número de asignaciones de memoria realizadas durante el intervalo de generación de perfiles.
  3. #Desasignación : el número de desasignaciones de memoria en el intervalo de generación de perfiles
  4. Capacidad de memoria : la capacidad total (en GiB) del sistema de memoria que seleccione.
  5. Uso máximo de almacenamiento dinámico: el uso máximo de memoria (en GiB) desde que el modelo comenzó a ejecutarse.
  6. Uso máximo de memoria: el uso máximo de memoria (en GiB) en el intervalo de generación de perfiles. Este campo contiene los siguientes subcampos:
    1. Marca de tiempo: la marca de tiempo de cuando se produjo el uso máximo de memoria en el gráfico de línea de tiempo.
    2. Reserva de pila : cantidad de memoria reservada en la pila (en GiB).
    3. Asignación de almacenamiento dinámico: cantidad de memoria asignada en el almacenamiento dinámico (en GiB).
    4. Free Memory : Cantidad de memoria libre (en GiBs). La capacidad de memoria es la suma total de la reserva de pila, la asignación de almacenamiento dinámico y la memoria libre.
    5. Fragmentación : el porcentaje de fragmentación (cuanto menos, mejor). Se calcula como un porcentaje de (1 - Size of the largest chunk of free memory / Total free memory) .

Gráfico de línea de tiempo de memoria

Esta sección muestra un gráfico del uso de la memoria (en GiB) y el porcentaje de fragmentación frente al tiempo (en ms).

imagen

El eje X representa la línea de tiempo (en ms) del intervalo de generación de perfiles. El eje Y de la izquierda representa el uso de memoria (en GiBs) y el eje Y de la derecha representa el porcentaje de fragmentación. En cada punto del tiempo en el eje X, la memoria total se divide en tres categorías: pila (en rojo), montón (en naranja) y libre (en verde). Pase el cursor sobre una marca de tiempo específica para ver los detalles sobre los eventos de asignación/desasignación de memoria en ese punto, como se muestra a continuación:

imagen

La ventana emergente muestra la siguiente información:

  • timestamp(ms) : La ubicación del evento seleccionado en la línea de tiempo.
  • event : El tipo de evento (asignación o desasignación).
  • request_size(GiBs) : La cantidad de memoria solicitada. Este será un número negativo para los eventos de desasignación.
  • asignación_size(GiBs) : la cantidad real de memoria asignada. Este será un número negativo para los eventos de desasignación.
  • tf_op : la operación de TensorFlow que solicita la asignación/desasignación.
  • step_id : El paso de entrenamiento en el que ocurrió este evento.
  • region_type : el tipo de entidad de datos para el que es esta memoria asignada. Los valores posibles son temp para temporales, output para activaciones y gradientes, y persist / dynamic para pesos y constantes.
  • data_type : el tipo de elemento tensor (p. ej., uint8 para un entero sin signo de 8 bits).
  • tensor_shape : La forma del tensor que se está asignando/desasignando.
  • memory_in_use(GiBs) : la memoria total que está en uso en este momento.

Tabla de desglose de memoria

Esta tabla muestra las asignaciones de memoria activa en el punto de uso máximo de memoria en el intervalo de creación de perfiles.

imagen

Hay una fila para cada TensorFlow Op y cada fila tiene las siguientes columnas:

  • Nombre de la operación: el nombre de la operación de TensorFlow.
  • Tamaño de asignación (GiBs) : la cantidad total de memoria asignada a esta operación.
  • Tamaño solicitado (GiBs) : la cantidad total de memoria solicitada para esta operación.
  • Ocurrencias : El número de asignaciones para esta op.
  • Tipo de región : el tipo de entidad de datos para el que es esta memoria asignada. Los valores posibles son temp para temporales, output para activaciones y gradientes, y persist / dynamic para pesos y constantes.
  • Tipo de datos : el tipo de elemento tensor.
  • Forma : la forma de los tensores asignados.

Visor de pods

La herramienta Pod Viewer muestra el desglose de un paso de capacitación entre todos los trabajadores.

imagen

  • El panel superior tiene un control deslizante para seleccionar el número de paso.
  • El panel inferior muestra un gráfico de columnas apiladas. Esta es una vista de alto nivel de categorías de tiempo de paso desglosadas colocadas una encima de la otra. Cada columna apilada representa un trabajador único.
  • Cuando pasa el cursor sobre una columna apilada, la tarjeta del lado izquierdo muestra más detalles sobre el desglose de pasos.

análisis de cuello de botella de tf.data

La herramienta de análisis de cuellos de botella tf.data detecta automáticamente los cuellos de botella en las canalizaciones de entrada de tf.data en su programa y proporciona recomendaciones sobre cómo solucionarlos. Funciona con cualquier programa que utilice tf.data independientemente de la plataforma (CPU/GPU/TPU). Su análisis y recomendaciones se basan en esta guía .

Detecta un cuello de botella siguiendo estos pasos:

  1. Encuentre el host con mayor límite de entrada.
  2. Encuentre la ejecución más lenta de una tubería de entrada tf.data .
  3. Reconstruya el gráfico de canalización de entrada a partir del seguimiento del generador de perfiles.
  4. Encuentre la ruta crítica en el gráfico de canalización de entrada.
  5. Identifique la transformación más lenta en la ruta crítica como un cuello de botella.

La interfaz de usuario se divide en tres secciones: Resumen de análisis de rendimiento , Resumen de todas las canalizaciones de entrada y Gráfico de canalización de entrada.

Resumen del análisis de rendimiento

imagen

Esta sección proporciona el resumen del análisis. Informa sobre canalizaciones de entrada lentas de tf.data detectadas en el perfil. Esta sección también muestra el host con mayor límite de entrada y su canal de entrada más lento con la latencia máxima. Lo que es más importante, identifica qué parte de la canalización de entrada es el cuello de botella y cómo solucionarlo. La información del cuello de botella se proporciona con el tipo de iterador y su nombre largo.

Cómo leer el nombre largo del iterador tf.data

Un nombre largo tiene el formato Iterator::<Dataset_1>::...::<Dataset_n> . En el nombre largo, <Dataset_n> coincide con el tipo de iterador y los otros conjuntos de datos en el nombre largo representan transformaciones posteriores.

Por ejemplo, considere el siguiente conjunto de datos de canalización de entrada:

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

Los nombres largos de los iteradores del conjunto de datos anterior serán:

Tipo de iterador Nombre largo
Rango Iterador::Lote::Repetir::Mapa::Rango
Mapa Iterador::Lote::Repetir::Mapa
Repetir Iterador::Lote::Repetir
Lote Iterador::Lote

Resumen de todas las canalizaciones de entrada

imagen

Esta sección proporciona el resumen de todas las canalizaciones de entrada en todos los hosts. Por lo general, hay una canalización de entrada. Cuando se usa la estrategia de distribución, hay una canalización de entrada de host que ejecuta el código tf.data del programa y múltiples canalizaciones de entrada de dispositivos que recuperan datos de la canalización de entrada de host y los transfieren a los dispositivos.

Para cada tubería de entrada, muestra las estadísticas de su tiempo de ejecución. Una llamada se considera lenta si tarda más de 50 μs.

Gráfico de canalización de entrada

imagen

Esta sección muestra el gráfico de canalización de entrada con la información del tiempo de ejecución. Puede usar "Host" y "Input Pipeline" para elegir qué host y canal de entrada desea ver. Las ejecuciones de la canalización de entrada se ordenan por el tiempo de ejecución en orden descendente, que puede elegir mediante el menú desplegable Clasificación .

imagen

Los nodos en la ruta crítica tienen contornos en negrita. El nodo de cuello de botella, que es el nodo con el tiempo propio más largo en la ruta crítica, tiene un contorno rojo. Los otros nodos no críticos tienen contornos discontinuos grises.

En cada nodo, Start Time indica la hora de inicio de la ejecución. El mismo nodo se puede ejecutar varias veces, por ejemplo, si hay una operación por Batch en la canalización de entrada. Si se ejecuta varias veces, es la hora de inicio de la primera ejecución.

La duración total es el tiempo de pared de la ejecución. Si se ejecuta varias veces, es la suma de los tiempos de pared de todas las ejecuciones.

Self Time es Total Time sin el tiempo superpuesto con sus nodos secundarios inmediatos.

"Número de llamadas" es la cantidad de veces que se ejecuta la canalización de entrada.

Recopilar datos de rendimiento

TensorFlow Profiler recopila actividades de host y seguimientos de GPU de su modelo de TensorFlow. Puede configurar Profiler para recopilar datos de rendimiento mediante el modo programático o el modo de muestreo.

API de creación de perfiles

Puede utilizar las siguientes API para realizar perfiles.

  • Modo programático usando 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 la API de función tf.profiler

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

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

  • Modo de muestreo: realice perfiles a pedido mediante tf.profiler.experimental.server.start para iniciar un servidor gRPC con la ejecución de su modelo TensorFlow. Después de iniciar el servidor gRPC y ejecutar su modelo, puede capturar un perfil a través del botón Capturar perfil en el complemento de perfil de TensorBoard. Use la secuencia de comandos en la sección Instalar perfilador anterior para iniciar una instancia de TensorBoard si aún no se está ejecutando.

    Como ejemplo,

    # 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)
    

    Un ejemplo para perfilar varios trabajadores:

    # 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)
    

Utilice el cuadro de diálogo Perfil de captura para especificar:

  • Una lista delimitada por comas de direcciones URL de servicios de perfil o nombres de TPU.
  • Una duración de perfilado.
  • El nivel de seguimiento de llamadas de función de dispositivo, host y Python.
  • Cuántas veces desea que Profiler vuelva a intentar capturar perfiles si no tiene éxito al principio.

Creación de perfiles de bucles de entrenamiento personalizados

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

El argumento de name se utiliza como prefijo para los nombres de los pasos, el argumento de la palabra clave step_num se agrega a los nombres de los pasos y el argumento de la palabra clave _r hace que el generador de perfiles procese este evento de rastreo como un evento de paso.

Como ejemplo,

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)

Esto habilitará el análisis de rendimiento basado en pasos de Profiler y hará que los eventos de paso se muestren en el visor de seguimiento.

Asegúrese de incluir el iterador del conjunto de datos dentro del contexto tf.profiler.experimental.Trace para un análisis preciso de la canalización de entrada.

El fragmento de código siguiente es un antipatrón:

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 creación de perfiles

El generador de perfiles 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:

  • Creación de perfiles local frente a remota : estas son dos formas comunes de configurar su entorno de creación de perfiles. En la generación de perfiles local, la API de generación de perfiles se llama en la misma máquina que ejecuta su modelo, por ejemplo, una estación de trabajo local con GPU. En la generación de perfiles remota, la API de generación de perfiles se llama en una máquina diferente de donde se ejecuta su modelo, por ejemplo, en una Cloud TPU.
  • Creación de perfiles de varios trabajadores : puede crear perfiles de varias máquinas al usar las capacidades de capacitación distribuida de TensorFlow.
  • Plataforma de hardware : Perfil de CPU, GPU y TPU.

La siguiente tabla proporciona una descripción general rápida de los casos de uso compatibles con TensorFlow mencionados anteriormente:

API de creación de perfiles Local Remoto Múltiples trabajadores Plataformas de hardware
Devolución de llamada de TensorBoard Keras Soportado No soportado No soportado CPU, GPU
API de inicio/detención tf.profiler.experimental Soportado No soportado No soportado CPU, GPU
API tf.profiler.experimental client.trace Soportado Soportado Soportado CPU, GPU, TPU
API de administrador de contexto Soportado No soportado No soportado CPU, GPU

Mejores prácticas para un rendimiento óptimo del modelo

Use las siguientes recomendaciones según corresponda para sus modelos de TensorFlow para lograr un rendimiento óptimo.

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

Optimizar la canalización de datos de entrada

Utilice los datos del [#input_pipeline_analyzer] para optimizar su canalización de entrada de datos. Una tubería de entrada de datos eficiente puede mejorar drásticamente la velocidad de ejecución de su modelo al reducir el tiempo de inactividad del dispositivo. Trate de incorporar las mejores prácticas detalladas en la guía Mejor rendimiento con la API tf.data y más abajo para hacer que su flujo de entrada de datos sea más eficiente.

  • En general, paralelizar cualquier operación que no necesite ejecutarse secuencialmente puede optimizar significativamente la canalización de entrada de datos.

  • En muchos casos, es útil cambiar el orden de algunas llamadas o ajustar los argumentos para que funcionen mejor para su modelo. Mientras optimiza la canalización de datos de entrada, compare solo el cargador de datos sin los pasos de entrenamiento y retropropagación para cuantificar el efecto de las optimizaciones de forma independiente.

  • Intente ejecutar su modelo con datos sintéticos para verificar si la canalización de entrada es un cuello de botella de rendimiento.

  • Utilice tf.data.Dataset.shard para el entrenamiento de múltiples GPU. Asegúrese de fragmentar muy pronto en el ciclo 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.

  • Paralelice varias operaciones configurando dinámicamente el valor de num_parallel_calls usando tf.data.AUTOTUNE .

  • Considere limitar el uso de tf.data.Dataset.from_generator , ya que es más lento en comparación con las operaciones puras de TensorFlow.

  • Considere limitar el uso de tf.py_function ya que no se puede serializar y no es compatible para ejecutarse en TensorFlow distribuido.

  • Utilice tf.data.Options para controlar las optimizaciones estáticas en la canalización de entrada.

Lea también la guía de análisis de rendimiento de tf.data para obtener más orientación sobre cómo optimizar su flujo de entrada.

Optimizar el aumento de datos

Cuando trabaje con datos de imágenes, haga que su aumento de datos sea más eficiente mediante la conversión a diferentes tipos de datos después de aplicar transformaciones espaciales, como voltear, recortar, rotar, etc.

Utilice NVIDIA® DALI

En algunos casos, como cuando tiene un sistema con una proporción alta de GPU a CPU, es posible que todas las optimizaciones anteriores no sean suficientes para eliminar los cuellos de botella en el cargador de datos causados ​​por las limitaciones de los ciclos de la CPU.

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

Consulte la documentación de NVIDIA® DALI: Operations para obtener una lista de las operaciones DALI admitidas.

Usar subprocesos y ejecución paralela

Ejecute operaciones en varios subprocesos de CPU con la API tf.config.threading para ejecutarlos más rápido.

TensorFlow establece automáticamente la cantidad de subprocesos de paralelismo de forma predeterminada. El grupo de subprocesos disponible para ejecutar operaciones de TensorFlow depende de la cantidad de subprocesos de CPU disponibles.

Controle la aceleración paralela máxima para una sola operación mediante tf.config.threading.set_intra_op_parallelism_threads . Tenga en cuenta que si ejecuta varias operaciones en paralelo, todas compartirán el grupo de subprocesos disponible.

Si tiene operaciones independientes sin bloqueo (operaciones sin ruta directa entre ellas en el gráfico), use tf.config.threading.set_inter_op_parallelism_threads para ejecutarlas simultáneamente usando el grupo de subprocesos disponible.

Misceláneas

Cuando trabaje con modelos más pequeños en GPU NVIDIA®, puede configurar tf.compat.v1.ConfigProto.force_gpu_compatible=True para forzar que todos los tensores de CPU se asignen con memoria anclada CUDA para dar un impulso significativo al rendimiento del modelo. Sin embargo, tenga cuidado al usar 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 prácticas recomendadas que se detallan aquí y en la guía de optimización del rendimiento de la GPU para optimizar el rendimiento del modelo de TensorFlow en el dispositivo.

Si usa GPU NVIDIA, registre la utilización de GPU y memoria en un archivo CSV ejecutando:

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

Configurar diseño de datos

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

Los formatos de datos del último canal mejoran la utilización de Tensor Core y brindan mejoras de rendimiento significativas, especialmente en modelos convolucionales cuando se combinan con AMP. Los diseños de datos de NCHW todavía pueden ser operados por Tensor Cores, pero introducen una sobrecarga adicional debido a las operaciones de transposición automática.

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

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

Maximiza la caché 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