Consejos de uso de MegEngine: manual del generador de perfiles

0.Escribe al frente

"xx, la respuesta de R al entrenamiento con múltiples máquinas es lenta, eche un vistazo a lo que está pasando".

"xxx, ¿por qué el entrenamiento de red de xxx se ralentiza después de la actualización de MGE? Echa un vistazo".

Esta es una conversación diaria dentro del grupo.

Entonces alguien asume la culpa todos los días.

¿El estado de los miembros del equipo es: mejorar el desempeño, mejorar el desempeño o TMD mejorar el desempeño?

Según estadísticas incompletas, el 80% de los problemas de rendimiento se deben en realidad a que el código de entrenamiento no está escrito lo suficientemente bien, lo que hace que MGE no pueda usarlo de manera efectiva.

Incluyendo, entre otras, las siguientes situaciones

1) fast_run no está habilitado

2) Utilice numpy con frecuencia para la sincronización

3) No utilice make_allreduce_cb, deje que la comunicación de cálculo sea en serie

4)。。。

Después de hacerlo muchas veces, descubrí que esto lleva demasiado tiempo y los pasos son los mismos cada vez. ¿Por qué tengo que hacerlo? Así que escribí este artículo para resumirlo para la conveniencia de todos y para mi propia conveniencia.

1.Introducción al perfilador

Primero debemos entender lo del Profiler.

En pocas palabras, Profiler registra el tiempo de ejecución de todos los operadores en forma de línea de tiempo.

A través de los resultados del perfil, podemos descubrir rápidamente por qué este código se ejecuta con lentitud.

¿Hiciste trabajo extra? ¿O es un desperdicio de recursos informáticos? O el desempeño del operador en sí es muy pobre y necesita ser reemplazado por otro operador.

1.png

Esta es una visualización de resultados de perfil simple.

En la mayoría de los casos, solo nos centramos en los subprocesos de gpu. Cada subproceso de gpu corresponde a un flujo de cuda, y los anteriores son todos los operadores que se ejecutan en este flujo de cuda.

2. Cómo utilizar

PD: La información estadística de las imágenes estáticas no es lo suficientemente perfecta (afectada por la optimización del gráfico) y los resultados del perfil no son lo suficientemente amigables en comparación con las imágenes dinámicas.

from megengine.utils.profiler import profile, Profiler
 
# 装饰器写法
@profile()
def train_step(data, label, *, optimizer, gm, model)
    with gm:
        logits = model(data)
        loss = F.loss.cross_entropy(logits, label)
        gm.backward(loss)
        optimizer.step().clear_grad()
    return loss
 
# with 写法
# 训练过程中最好只有一个profiler实例,因为profiler会在析构时自动dump出结果,如果有多个实例的话每个iter都会dump,非常慢
profiler = Profiler()
 
def train_step(data, label, *, optimizer, gm, model)
    with profiler:
       with gm:
           logits = model(data)
           loss = F.loss.cross_entropy(logits, label)
           gm.backward(loss)
           optimizer.step().clear_grad()
    return loss

⚠️Tenga en cuenta que el perfilador exportará los resultados del perfil durante la destrucción de forma predeterminada. También puede llamar manualmente al método perfilador.dump para realizar el volcado manualmente.

Descripción de parámetros:

Profiler El constructor admite los siguientes parámetros:

  • ruta: la ruta de almacenamiento de los datos del perfil, que de forma predeterminada es la carpeta del perfil en la ruta actual.
  • formato: el formato de los datos de salida, el valor predeterminado es chrome_timeline.json, que es un formato estándar compatible con Chrome y muestra los resultados de la creación de perfiles en forma de línea de tiempo. También existe la opción Memory_flow.svg, que muestra el uso de la memoria en la forma de tiempo x espacio de direcciones.Condición.
  • formatos: si se requiere más de un formato de salida, se puede enumerar en el parámetro de formatos.
  • sample_rate: si este elemento no es cero, la información de la memoria de video se contará cada n operaciones y la curva de uso de la memoria de video se puede dibujar al analizar los datos. El valor predeterminado es 0.
  • perfil_device: ya sea para registrar el consumo de tiempo de la GPU, el valor predeterminado es Verdadero.
  • with_scopes: si se debe registrar adicionalmente el alcance correspondiente a la API de Python, como el método funcional/tensor, el valor predeterminado es Falso. 
  • with_backtrace: si se debe registrar la pila de llamadas de Python correspondiente a la operación/evento. El valor predeterminado es Falso. Al activarlo, aumentará el tamaño del archivo de datos grabado.

Introducción al uso del alcance

Agregaremos automáticamente alcance a los pasos de avance, retroceso y paso del módulo. El alcance se mostrará en el hilo del host y podrá ver a qué módulo pertenece la operación y en qué etapa.

2.png

También puedes agregar alcance tú mismo

from megengine.utils.profiler import Profiler, scope
 
def main()
    with Profiler():
        x = Tensor(1)
        with scope("Add"):
            y = x+1
        with scope("Mul"):
            z = x*3

De forma predeterminada, Profiler solo registrará los alcances de avance, retroceso y paso del módulo. Los usuarios pueden pasar parámetros with_scopes = Truepara registros adicionales al construir el objeto Profiler  functionaly llamar a los correspondientes .tensor methodapiscope

Después de activar la opción, with_scopesse graban llamadas BatchNorm2d Moduleinternas adicionales.functional / tensor method APIscope

3.pngDespués de activar la opción with_scopes, se registra un alcance hacia atrás adicional. Este alcance se usa para registrar el operador directo correspondiente a la secuencia de cálculo inverso. Se puede usar para encontrar qué operador genera el cálculo directo para el operador con problemas de rendimiento en el cálculo inverso. El alcance en la figura siguiente representa Broadcast, SetSubtensor y otros operadores se generan mediante el cálculo inverso de Subtensor.

4.png

3. Pantalla visual

Se recomienda usar  perfetto  para ver los resultados del perfil. También puede usar el módulo de rendimiento del modo de desarrollador de Chrome (F12) para ver el archivo en formato de línea de tiempo. También puede usar chrome://tracing/  para  verlo .

A continuación se presentan los métodos de operación basados ​​en perfetto.

1) Estadísticas

Puede seleccionar un período de tiempo continuo para ver los resultados estadísticos de este período de tiempo.

Los resultados de las estadísticas del evento se mostrarán a continuación. Puede ver el tiempo de ocupación real del evento (duración del muro) (el tiempo de inactividad se puede calcular en función del tiempo total). Puede ordenar por el tiempo de ocupación total o por el tiempo promedio. .

5.png

2) Dependencias

En el hilo del host, la operación registrará la entrada y salida correspondientes y las dependencias correspondientes. Puede encontrar la operación anterior de la que depende la entrada según la flecha, o puede hacer clic en el evento de flujo a continuación para pasar a la anterior o el proximo.

6.png

7.png

También podemos encontrar el tiempo del host y el tiempo de gpu correspondientes a la operación. Haga clic en la operación para ver el tiempo ocupado por diferentes subprocesos (cpu, gpu)

8.png

3) Ver indicadores como el uso de la memoria de video y la utilización de la GPU

Además de registrar el tiempo de ejecución del operador de tiempo, el generador de perfiles también registra algunos indicadores relacionados con la memoria de video y el rendimiento. gpu_usage_ratio registra la utilización promedio de gpu de la ejecución del programa (la proporción del tiempo de ejecución del kernel de gpu con respecto al tiempo total). Un gpu_usage_ratio bajo indica que el lado host del programa es un cuello de botella. gpux:x alloc_mem_value registra la curva de uso de la memoria de video de gpux que cambia con el tiempo. Sample_rate debe configurarse en un número entero mayor que 0 (la velocidad de muestreo significa registrar el uso de la memoria de video cada n operaciones)

9.png

4) Acercar y alejar

Puede arrastrar los puntos de inicio y finalización de la línea de tiempo de arriba para modificar los puntos de inicio y finalización, o puede acercar y alejar usando gestos de zoom.

El pequeño cuadrado gris sobre la línea vertical central es el punto que se puede arrastrar

10.png 11.png

4. Técnicas de depuración comunes (con ejemplos de uso)

1) Cálculos redundantes

12.pngEn el ejemplo de yolox, las operaciones de avance, retroceso y paso se completan, pero hay muchas operaciones de remodelación posteriores (generalmente se cree que la remodelación no tiene cálculo real, por lo que básicamente se considera un desperdicio).

Después de encontrar la causa, los resultados son los siguientes (5s->1,3s)

13.png

2) Calcule la comunicación en serie (busque make_allreduce_cb)

La comunicación Allreduce está en gpu0: 1. Si descubre que la comunicación está en gpu0: 0, la está usando incorrectamente.

14.png

3) El rendimiento del host es lento y la utilización de la GPU no es alta.

15.png

El tiempo de la CPU y el tiempo de la GPU son básicamente los mismos, lo cual es muy sospechoso.

Acérquese y mire con atención. Hay muchas brechas en el tiempo de ejecución de la GPU. Haga clic en la operación correspondiente para ver las dependencias. Puede ver que la brecha de tiempo en el medio está esperando que el host inicie el kernel cuda.

16.png

4) Utilice la función de grabación de seguimiento para encontrar el código fuente correspondiente a la parte del cuello de botella de rendimiento.

El ejemplo anterior presenta cómo encontrar partes de rendimiento anormales a partir de los resultados del perfil. El generador de perfiles proporciona la función de grabación de la pila de llamadas de seguimiento inverso para facilitar a los usuarios encontrar el código fuente del código de entrenamiento correspondiente a las partes anormales. El registro de seguimiento registrará la ejecución de despacho/kernel del operador y la pila de llamadas de Python correspondiente a TensorWaitProperty y otros eventos. 

Puede activar la función de grabación de la pila de llamadas pasando with_backtrace = True al construir el objeto Profiler. Después de activar esta opción, aumentará el tamaño del archivo de datos guardado del generador de perfiles.

Los usuarios pueden hacer clic en op en la interfaz UI de perfetto para ver su código fuente correspondiente.

En los resultados del generador de perfiles en la figura siguiente, el operador CompiledOp[IOU] tarda mucho en ejecutarse. A través del seguimiento registrado, podemos encontrar que este operador se llama en la parte de cálculo de pérdidas del modelo de detección.

17.png

En la siguiente figura, un determinado TensorWaitProp en el subproceso del intérprete lleva mucho tiempo, lo que puede ralentizar la velocidad de ejecución del host y hacer que la GPU quede inactiva.

(TensorWaitProp puede ser generado por tensor.shape, tensor.numpy() y otras llamadas a métodos, lo que hará que el lado del host espere la ejecución del dispositivo para obtener el valor o el atributo de forma de Tensor)

A través de la pila de llamadas, se puede encontrar que el evento es generado por un getitem en el método get_ground_truth del modelo de detección basado en (el atributo de forma del tensor se usa en __getitem__ para activar la sincronización en el lado del host).18.png

adjunto

Para obtener más información sobre MegEngine, puede: ver la documentaciónel proyecto GitHub , o unirse al grupo QQ de comunicación de usuarios de MegEngine: 1029741705. Bienvenido a contribuir a la comunidad MegEngine y convertirse en un  Awesome MegEngineer , y disfrutar de infinitos certificados de honor y obsequios personalizados.

Alibaba Cloud sufrió un grave fallo que afectó a todos los productos (ha sido restaurado). El sistema operativo ruso Aurora OS 5.0, una nueva interfaz de usuario, se presentó en Tumblr. Muchas empresas de Internet reclutaron urgentemente programadores de Hongmeng . .NET 8 es oficialmente GA, el último Versión LTS Tiempo UNIX A punto de ingresar a la era de los 1.7 mil millones (ya ingresó), Xiaomi anunció oficialmente que Xiaomi Vela es completamente de código abierto y el kernel subyacente es .NET 8 en NuttX Linux. El tamaño independiente se reduce en un 50%. FFmpeg 6.1 " Se lanza Heaviside". Microsoft lanza una nueva "aplicación para Windows"
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/5265910/blog/10105776
Recomendado
Clasificación