Mientras depuraba un problema de rendimiento en la aplicación en la que estoy trabajando, descubrí un comportamiento extraño del programador del kernel. Parece que las tareas SCHED_FIFO ocupadas tienden a programarse en núcleos lógicos de la misma CPU física aunque haya CPU físicas inactivas en el sistema.
8624 root -81 0 97.0g 49g 326m R 100 52.7 48:13.06 26 Worker0 <-- CPU 6 and 26 8629 root -81 0 97.0g 49g 326m R 100 52.7 44:56.26 6 Worker5 <-- the same physical core 8625 root -81 0 97.0g 49g 326m R 82 52.7 58:20.65 23 Worker1 8627 root -81 0 97.0g 49g 326m R 67 52.7 55:28.86 27 Worker3 8626 root -81 0 97.0g 49g 326m R 67 52.7 46:04.55 32 Worker2 8628 root -81 0 97.0g 49g 326m R 59 52.7 44:23.11 5 Worker4Inicialmente, los subprocesos se mezclan entre núcleos, pero en algún momento, la mayoría de los subprocesos intensivos en CPU terminan bloqueados en el mismo núcleo físico y no parecen moverse desde allí. No hay un conjunto de afinidades para los subprocesos de Worker.
Traté de reproducirlo con carga sintética ejecutando 12 instancias de:
chrt -f 10 yes > /dev/null &Y esto es lo que obtuve:
25668 root -11 0 2876 752 656 R 100 0.0 0:17.86 20 yes 25663 root -11 0 2876 744 656 R 100 0.0 0:19.10 25 yes 25664 root -11 0 2876 752 656 R 100 0.0 0:18.79 6 yes 25665 root -11 0 2876 804 716 R 100 0.0 0:18.54 7 yes 25666 root -11 0 2876 748 656 R 100 0.0 0:18.31 8 yes 25667 root -11 0 2876 812 720 R 100 0.0 0:18.08 29 yes <--- core9 25669 root -11 0 2876 744 656 R 100 0.0 0:17.62 9 yes <--- core9 25670 root -11 0 2876 808 720 R 100 0.0 0:17.37 2 yes 25671 root -11 0 2876 748 656 R 100 0.0 0:17.15 23 yes <--- core3 25672 root -11 0 2876 804 712 R 100 0.0 0:16.94 4 yes 25674 root -11 0 2876 748 656 R 100 0.0 0:16.35 3 yes <--- core3 25673 root -11 0 2876 812 716 R 100 0.0 0:16.68 1 yesEste es un servidor con 20 núcleos físicos, por lo que quedan 8 núcleos inactivos y los subprocesos todavía están programados en el mismo núcleo físico. Esto es reproducible y persistente. No parece suceder para subprocesos que no sean SCHED_FIFO. También comenzó después de migrar más allá del kernel 4.19.
¿Es este comportamiento correcto para subprocesos SCHED_FIFO? ¿Hay alguna opción de configuración o indicador que pueda cambiar el comportamiento de este programador?
Si entiendo correctamente, está tratando de usar SCHED_FIFO con hyperthreading ("HT") habilitado, lo que da como resultado múltiples procesadores de subprocesos por núcleo físico. Tengo entendido que la conciencia de HT dentro del kernel de Linux se produce principalmente a través de los dominios de equilibrio de carga y programador dentro de CFS (el programador predeterminado en estos días). Consulte https://stackoverflow.com/a/29587579/2530418 para obtener más información.
El uso SCHED_FIFO o SCHED_RR esencialmente evitaría el manejo de HT, ya que la programación de RT realmente no pasa por CFS.
Mi enfoque para lidiar con esto en el pasado ha sido deshabilitar el hiperprocesamiento. Para los casos en los que realmente necesita un comportamiento en tiempo real, esta suele ser la compensación correcta de latencia/rendimiento de todos modos (consulte https://rt.wiki.kernel.org/index.php/HOWTO:_Build_an_RT-application#Hyper_threading ). Si esto es apropiado realmente depende del problema que esté tratando de resolver.
Aparte: sospecho que si realmente necesita el comportamiento SCHED_FIFO , entonces deshabilitar HT es lo que querrá hacer, pero también es común que las personas piensen que necesitan SCHED_FIFO cuando es la herramienta incorrecta para el trabajo. Mi sospecha es que puede haber una mejor opción que usar SCHED_FIFO ya que está describiendo la ejecución en un servidor convencional en lugar de un sistema integrado, pero esa es una suposición que generaliza demasiado. Difícil de decir sin más detalles sobre el tema.
El problema fue causado por este cambio en particular: https://lkml.iu.edu/hypermail/linux/kernel/1806.0/04887.html
Se eliminaron los subprocesos de vigilancia por núcleo de CPU
watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);Antes, se ejecutaban periódicamente cada 4 segundos y debido a que eran absolutamente de máxima prioridad, provocaban una reprogramación periódica. Cuando se han ido, no hay nada que pueda adelantarse a mis subprocesos SCHED_FIFO y migrarlos a un núcleo "mejor". Entonces, todo esto fue solo un efecto secundario de la implementación del perro guardián. En general, no existe ningún mecanismo en el kernel que realice el reequilibrio de los subprocesos RT fuera de control.