Perfilado de código CFD con Callgrind

16

Estoy usando Valgrind + Callgrind para perfilar un solucionador que he escrito. Como dice el manual de usuario de Valgrind, he compilado mi código con las opciones de depuración para el compilador:

"Sin información de depuración, las mejores herramientas de Valgrind serán capaces de adivinar a qué función pertenece un código en particular, lo que hace que los mensajes de error y la producción de perfiles sean casi inútiles. Con -g, obtendrá mensajes que apuntan directamente a las líneas de código fuente relevantes ".

Manual de Valgrind

Cuando se compila con la opción de depuración, los códigos se ejecutan mucho más lentamente. El código CFD se vuelve REALMENTE lento, incluso en casos pequeños cuando se compila con indicadores de depuración. Valgrind lo hace 40 veces más lento (consulte el manual 1 ).

  1. ¿Qué herramientas está utilizando para la creación de perfiles de código (creación de perfiles, no evaluación comparativa)?

  2. ¿Cuánto tiempo dejas correr el código (estadísticas: cuántos pasos de tiempo)?

  3. ¿Qué tan grandes son los casos (si el caso cabe en el caché, el solucionador es un orden de magnitud más rápido, pero luego extrañaré los procesos relacionados con la memoria)?

tmarico
fuente
3
Puede compilar el código con símbolos de depuración y optimización habilitados. Aún así, 40x a través de valgrind (que simula todo el acceso a la memoria) no es irrazonable.
Aron Ahmadia
Gracias, esto es lo que también he leído ... lo que me gustaría saber son informaciones sobre las experiencias cotidianas en la creación de perfiles (con valgrind preferiblemente): cuánto tiempo es normal esperar los informes, cuántas iteraciones recuento que necesito, ¿qué puedo excluir ... etc ...
tmaric
Tu pregunta también es un poco amplia. Recomiendo editar su pregunta para centrarse en Q2.1 y Q2.2, ya que Q1 es una pregunta completamente diferente (me alegra que la haga por separado, es una buena pregunta, pero dígala como "¿Qué herramientas usaría? úselo para resolver el problema X ", ¡donde X está bien descrito!), mientras que Q2 por sí solo es demasiado general.
Aron Ahmadia
Puede también editar a nombre de callgrind, cachegrindo massif. Muchas personas asocian Valgrind solo con la herramienta predeterminada ( memcheck). Como sistema de creación de perfiles basado en emulación (en lugar de interrupción), no debería necesitar ejecutarse durante mucho tiempo.
Jed Brown
@Aron y Jed: gracias por los consejos, he editado la pregunta. :)
tmaric

Respuestas:

11

P1: ¿Qué herramientas está utilizando para la creación de perfiles de código (creación de perfiles, no evaluación comparativa)?

P2: ¿Cuánto tiempo dejas que se ejecute el código (estadísticas: cuántos pasos de tiempo)?

P3: ¿Qué tan grandes son los casos (si el caso cabe en la memoria caché, el solucionador es un orden de magnitud más rápido, pero luego extrañaré los procesos relacionados con la memoria)?

Aquí hay un ejemplo de cómo lo hago.

Separo el benchmarking (viendo cuánto tiempo lleva) del perfilado (identificando cómo hacerlo más rápido). No es importante que el perfilador sea rápido. Es importante que le diga qué arreglar.

Ni siquiera me gusta la palabra "perfil" porque evoca una imagen algo así como un histograma, donde hay una barra de costos para cada rutina, o "cuello de botella" porque implica que hay un pequeño lugar en el código que debe ser fijo. Ambas cosas implican algún tipo de tiempo y estadísticas, por lo que asume que la precisión es importante. No vale la pena renunciar a la comprensión de la precisión del tiempo.

El método que uso es una pausa aleatoria, y hay un estudio de caso completo y una presentación de diapositivas aquí . Parte de la visión del mundo del cuello de botella del perfilador es que si no encuentra nada, no se puede encontrar nada, y si encuentra algo y obtiene un cierto porcentaje de aceleración, declara la victoria y renuncia. Los fanáticos de Profiler casi nunca dicen cuánto aceleran, y los anuncios solo muestran problemas artificiales diseñados para ser fáciles de encontrar. La pausa aleatoria encuentra los problemas, ya sean fáciles o difíciles. Luego, solucionar un problema expone otros, por lo que el proceso puede repetirse, para obtener una aceleración compuesta.

En mi experiencia con numerosos ejemplos, así es como funciona: puedo encontrar un problema (haciendo una pausa aleatoria) y solucionarlo, obteniendo una aceleración de un porcentaje, digamos 30% o 1.3x. Entonces puedo hacerlo de nuevo, encontrar otro problema y solucionarlo, obteniendo otra aceleración, tal vez menos del 30%, tal vez más. Entonces puedo hacerlo de nuevo, varias veces hasta que realmente no pueda encontrar nada más que arreglar. El factor de aceleración final es el producto en ejecución de los factores individuales, y puede ser asombrosamente grande: órdenes de magnitud en algunos casos.

INSERTADO: Solo para ilustrar este último punto. Hay un ejemplo detallado aquí , con la presentación de diapositivas y todos los archivos, que muestra cómo se logró un aumento de velocidad de 730x en una serie de suspensiones de problemas. La primera versión tomó 2700 microsegundos por unidad de trabajo. El problema A se eliminó, reduciendo el tiempo a 1800 y ampliando los porcentajes de los problemas restantes en 1.5x (2700/1800). Entonces B fue eliminado. Este proceso continuó a través de seis iteraciones, resultando en casi 3 órdenes de aceleración de magnitud. Pero la técnica de creación de perfiles tiene que ser realmente eficaz, porque si no se encuentra alguno de esos problemas, es decir, si llega a un punto en el que cree incorrectamente que no se puede hacer nada más, el proceso se detiene.

Descripción de la eliminación de múltiples problemas para obtener una gran velocidad

INSERTADO: Para decirlo de otra manera, aquí hay un gráfico del factor de aceleración total a medida que se eliminan los problemas sucesivos:

ingrese la descripción de la imagen aquí

Entonces, para Q1, para la evaluación comparativa es suficiente un temporizador simple. Para "perfilar", uso una pausa aleatoria.

P2: le doy suficiente carga de trabajo (o simplemente le doy un bucle) para que funcione lo suficiente como para pausar.

P3: Por supuesto, dele una carga de trabajo realmente grande para que no se pierda los problemas de caché. Esos aparecerán como ejemplos en el código haciendo las recuperaciones de memoria.

Mike Dunlavey
fuente
Mike, ¿tienes preferencia sobre cómo hacer pausas aleatorias en ausencia de un IDE visual? ¿Se puede automatizar este proceso de alguna manera?
Matthew Emmett
@Matthew: Entiendo que hay herramientas como pstacky lsstack, pero realmente considero que este es un proceso más en común con la depuración. Entonces, incluso si el mejor depurador que puedo soportar es gdb, hace el trabajo. Con un depurador puede examinar los datos, y eso puede marcar la diferencia cuando la pila por sí sola no le dice lo suficiente.
Mike Dunlavey
9

El perfilador del pobre es básicamente un gdbscript que muestra la pila de llamadas. Aún necesitará tener símbolos de depuración. Todavía es lento, pero como no implementa una máquina virtual para ejecutar el código, a menudo es más rápido callgrindy adecuado para la tarea.

Me he encontrado con analizadores de física de partículas con un éxito modesto (es decir, demostré que el código no tenía puntos calientes horribles y que la optimización requeriría un algoritmo mejor).

dmckee
fuente
1
+ La ausencia de evidencia no es evidencia de ausencia :) Lo que el perfilador de ese pobre hombre debe hacer es tomar menos rastros y no colapsarlos, sino dejar que los vea. El ojo humano es mucho mejor para detectar patrones útiles que las simples estimaciones de tiempo de función, y si ve algo que podría mejorar con tan solo 2 muestras, será de gran ayuda. La fracción X que guardará es una distribución beta con el modo 2 / N, donde N es la cantidad de trazas que examinó, y el factor de aceleración será 1 / (1-X), que puede ser grande.
Mike Dunlavey
2

Para agregar a las excelentes respuestas disponibles, hay una herramienta desarrollada en Rice que automatiza el muestreo de la pila y, por lo tanto, tiene muy poca sobrecarga:

http://hpctoolkit.org/

Reid.Atcheson
fuente
Eso se ve bien, aunque (lo siento) me he puesto mi sombrero de llamas aquí. No sintonizo el código optimizado por el compilador porque es difícil ver lo que está sucediendo en el código destrozado. Las cosas que estoy eliminando no son cosas con las que el optimizador podría lidiar, como llamar expy logcon los mismos argumentos repetidamente, u operaciones matriciales que pasan todas sus opciones de decodificación de tiempo. Sintonizo todo lo que puedo, luego enciendo -O3.
Mike Dunlavey
Las herramientas son herramientas y solo son útiles si el usuario conoce y comprende sus limitaciones. No creo que haya un "perfilador perfecto" que elimine al usuario de la ecuación por completo con respecto a comprender su salida y saber cómo usar la información.
Reid.Atcheson
1

Allinea MAP es un generador de perfiles de muestreo compatible y desarrollado comercialmente y, por lo tanto, como HPC Toolkit sugirió en una respuesta anterior, puede ejecutarse en trabajos de producción si lo desea.

Este tipo de herramienta apunta a los cuellos de botella de la CPU o la mala comunicación de MPI, pero también la supervisión completa de la elaboración de perfiles de todo el trabajo puede ser invaluable para encontrar problemas sorpresa.

A menudo hay frutos de bajo rendimiento que se encuentran fuera del núcleo de un código CFD, en áreas que no se esperaban. El muestreo aleatorio de la pila es, ya sea de forma manual con GDB o con herramientas como HPC Toolkit y Allinea MAP, la mejor manera de encontrarlos. Si algo es importante para el rendimiento, aparecerá.

David
fuente