Durante los últimos dos días estuve mirando varios gráficos de perfiles de memoria de GPU. No hay mucha información disponible sobre cómo interpretarlos, así que escribí un script para hacerlo en una sola línea y escribí una entrada de blog. Entonces, ¿qué significan todas esas formas extrañas? Tutorial rápido🧵
Primero, para perfilar cualquier bloque de código, simplemente coloque este archivo Python en su proyecto y use un código como egithub.com/sytelus/nanugp…r datos de perfil: https://t.co/iYTzEFksVR
Obtendrá una visualización como la siguiente. Inmediatamente podrá ver tres patrones repetitivos para tres pasos de entrenamiento. ¡Un buen comienzo! Esas franjas indican las operaciones de memoria capa por capa. La banda constante a continuación representa los parámetros del modelo y los estados del optimizador. ¿Pero qué son todas esas cosas?
Analicemos el primer paso del entrenamiento. Comienza con un semitriángulo, que es un pase hacia adelante. Termina con la creación de logits, que es un paralelogramo rojo gigante. El pico agudo al inicio es la memoria temporal para softmax. La razón por la que los logits son tan grandes es porque el vocabulario es de 151k.
A continuación, llamamos a zero_grad(), que borra las asignaciones antiguas de .grad. Al final de zero_grad(), se produce un pequeño pico y luego un gran desnivel. El pico se produce cuando .backward() comienza en softmax y el desnivel se debe a que el tensor logits ya no es necesario. Esto produce grados de carga del LM (banda verde).
En la imagen de arriba, observe el patrón ondulante a la derecha. Esto se debe a que he habilitado los puntos de control de activación. Esto hace que cada capa vuelva a calcular las activaciones, lo que genera pequeños picos y también libera su tensor de entrada a medida que .backward() avanza capa por capa.
Finalmente, mi parte favorita: optimizer.step(). Es increíblemente hermoso, como un templo con un asta de bandera. Se asienta sobre dos cimientos. La franja naranja es, en realidad, la gradación de la capa de incrustación producida al final de .backward().
En la imagen superior, la franja verde representa el almacenamiento necesario para almacenar la raíz cuadrada de grad^2 para Adam. Adam fusionado calcula las actualizaciones para aplicarlas capa por capa, lo que genera franjas. En la parte superior, aplica esas actualizaciones de una sola vez. El pico representa el búfer temporal necesario para la división antes de aplicar la actualización.
Hay mucho más que decir sobre estas hermosas visualizaciones. Por favor, avísenme si encuentran algún error o cualquier otra información interesante que debamos saber. Más en mi blog: Cómo obteshital.com/blog/gpu-memor…rfil de memoria de la GPU https://t.co/3uPt0S6RIp





