Estoy tratando de optimizar una aplicación MPI con un patrón de comunicación altamente asíncrono. Cada rango tiene una lista de cosas para calcular y envía mensajes según sea necesario si las entradas o salidas residen en un rango diferente. Además, cada rango está enhebrado (actualmente con un hilo de comunicación y 5 trabajadores).
He instrumentado el código con temporizadores en torno a las diferentes porciones críticas de rendimiento del código, lo que me da una lista de (inicio, fin, tipo) triples para cada hilo. Trazado de manera obvia, con el tiempo como eje horizontal, rango e hilo como vertical, y el color indicando lo que cada hilo está haciendo actualmente, obtengo una imagen como esta para 16 rangos con 6 hilos / rango:
Mi pregunta es: ¿cuáles son otras formas de visualizar estos datos que podrían ayudar a detectar problemas de rendimiento? ¿Alguien tiene un tipo de diagrama favorito que usan al perfilar aplicaciones asincrónicas?
Este conjunto de datos es limitado porque no conoce la estructura del flujo de datos, pero me gustaría obtener la mayor cantidad de información posible antes de intentar recopilar algo más complicado.
La imagen sin comprimir está aquí en caso de que alguien quiera mirar alrededor (no se pudo cargar a través de la ruta normal). Desafortunadamente, Firefox no lo acepta a pesar de que creo que es válido, posiblemente porque es simplemente demasiado grande.
fuente
Respuestas:
Paso mucho tiempo escribiendo y depurando código paralelo, tanto con memoria compartida como distribuida, pero sin conocer su problema específico, solo puedo decirle qué funciona mejor para mí.
Sabiendo que las rutinas toman la cantidad de tiempo es una cosa importante si usted está buscando en la eficiencia computacional, pero si usted está preocupado acerca de la eficiencia en paralelo, entonces deberían estar más preocupados por lo que el código está haciendo cuando se está sin hacer ningún cálculo. Es como preocuparse por lo que hacen los niños cuando está demasiado tranquilo ...
Dado que está utilizando un enfoque de memoria compartida / distribuida híbrida, supongo que su código, en los espacios en blanco, está esperando una llamada MPI o en una variable mutex / condición. También puede envolver estas llamadas en temporizadores, y eso le dará una mejor idea de lo que lo está frenando, por ejemplo, si siempre es el mismo condicional o siempre el mismo en el
MPI_REDUCE
que se atascan sus hilos.Una pieza de software que uso con bastante frecuencia es el Intel Vtune Amplifier XE . Tiene una buena característica / opción de trazado que visualiza la concurrencia de hilos. El programa trazará una trama muy similar a la suya, pero cuando un hilo espera en un mutex o variable de condición, dibuja una línea diagonal desde el hilo en espera, en el momento en que comenzó a esperar, hasta el hilo que realmente liberó el mutex o señaló la condición que estaba esperando, en el momento en que fue liberado / señalizado. Esto puede ser bastante complicado, pero hace que los cuellos de botella aparezcan de inmediato.
Finalmente, también recopilo estadísticas masivas, por ejemplo, para cada llamada mutex / señal / MPI, ¿cuáles fueron los tiempos de espera promedio y máximo? ¿Cuál es el histograma de los tiempos de espera recopilados? Si bien la trama le brinda una buena visión general, puede ser bastante desordenada cuando se trata de detalles finos.
Finalmente, una pregunta que no debe ser subestimada: ¿Cómo está recopilando sus tiempos? ¿Su temporizador no es lo suficientemente intrusivo como para no influir en su código? Uso el recuento de instrucciones de la CPU siempre que sea posible, es decir,
RDTSC
en arquitecturas x86. Esto generalmente solo agrega una sola instrucción a su código.fuente
constant_tsc
indicador establecido (verificar/proc/cpuinfo
) y si usa bloquear cada hilo en un núcleo específico, es decir, cada hilo siempre lee el mismo registro del mismo núcleo, por ejemplo, usandopthread_setaffinity_np
. Tenga en cuenta que este último es específico de Linux y, por lo tanto, no es portátil.MPI_Waitsome
, aún puede registrar qué solicitudes llegaron realmente y de dónde. Esta información puede o no ser útil ...A veces puede obtener una visión alternativa sobre los problemas de rendimiento a través de un análisis de recursos de alto nivel: ¿Existe un cuello de botella relevante como el ancho de banda de la memoria? ¿Cada hilo de trabajo hace la misma cantidad de trabajo? Estos datos pueden recopilarse fácilmente con likwid-perfctr del proyecto de código de Google LIKWID del conjunto de herramientas LIKWID . Si el perfil es tal que existen muchos puntos calientes diferentes, es posible que deba abordarlos uno por uno. También puede haber diferentes problemas, dependiendo de cuántos hilos / procesos se utilicen.
fuente
Cuando tengo un problema en una red de procesos altamente asincrónicos regidos por mensajes o eventos, utilizo un método que no es fácil pero es efectivo. Implicaba obtener registros de los procesos con marca de tiempo, fusionándolos en una línea de tiempo común y rastreando el progreso de algunos mensajes a medida que desencadenan actividades, desencadenando más mensajes. Lo que estoy buscando es un retraso entre el momento en que se recibe un mensaje y el momento en que se actúa, y entender el motivo del retraso. Cuando se encuentra un problema, se soluciona y el proceso se repite. De esta manera, puede obtener un rendimiento realmente satisfactorio.
Es importante ver cómo esto difiere de los enfoques en los que mide, mide, mide. Lo único que la medición puede decirle es dónde no mirar. El ajuste de rendimiento real requiere mirar cuidadosamente los detalles, desde una perspectiva de tiempo. Lo que está buscando no es dónde se gasta el tiempo, sino donde se gasta innecesariamente.
Buena suerte.
fuente