Tenemos varios programas de estilo de "canalización" sensibles a la latencia que tienen una degradación de rendimiento mensurable cuando se ejecutan en un kernel Linux frente a otro. En particular, vemos un mejor rendimiento con el kernel 2.6.9 CentOS 4.x (RHEL4) y un peor rendimiento con el kernel 2.6.18 de CentOS 5.x (RHEL5).Diferencias de programación de hilos de Linux en sistemas multi-core?
Por "canalización", me refiero a uno que tiene múltiples hilos. Los hilos mutiple funcionan en datos compartidos. Entre cada hilo, hay una cola. Entonces, el subproceso A obtiene datos, ingresa Qab, el subproceso B extrae de Qab, procesa algo, luego presiona Qbc, tira C de Qbc, etc. Los datos iniciales son de la red (generados por un tercero).
Básicamente, medimos el tiempo desde que se reciben los datos hasta cuando el último hilo realiza su tarea. En nuestra aplicación, vemos un aumento de entre 20 y 50 microsegundos al pasar de CentOS 4 a CentOS 5.
He utilizado algunos métodos de creación de perfiles de nuestra aplicación, y he determinado que la latencia agregada en CentOS 5 proviene de operaciones de cola (en particular, reventado).
Sin embargo, puedo mejorar el rendimiento en CentOS 5 (para ser lo mismo que CentOS 4) mediante el uso del conjunto de tareas para vincular el programa a un subconjunto de los núcleos disponibles.
Me parece que, entre CentOS 4 y 5, hubo algún cambio (presumiblemente en el kernel) que provocó que los hilos se programaran de manera diferente (y esta diferencia no es óptima para nuestra aplicación).
Aunque puedo "resolver" este problema con taskset (o en código a través de sched_setaffinity()), mi preferencia es no tener que hacer esto. Espero que haya algún tipo de parámetro optimizable del kernel (o quizás una colección de parámetros optimizables) cuyo valor por defecto haya cambiado entre versiones.
¿Alguien tiene alguna experiencia con esto? Tal vez algunas áreas más para investigar?
Actualización: En este caso particular, el problema se resolvió mediante una actualización del BIOS del proveedor del servidor (Dell). Me saqué el pelo bastante tiempo en este caso. Hasta que volví a lo básico y verifiqué las actualizaciones de BIOS de mi proveedor. Sospechosamente, una de las actualizaciones decía algo así como "mejorar el rendimiento en el modo de máximo rendimiento". Una vez que actualicé el BIOS, CentOS 5 fue más rápido, hablando en términos generales, pero particularmente en mis pruebas de cola y las ejecuciones de producción reales.
Las operaciones de dequeueing solo tienen un impacto en el rendimiento en el caso más lento, es decir, el nuevo kernel RHEL5. Basado en mis experimentos, mi mejor explicación para esto es que los diferentes hilos están programados en núcleos de tal manera que se pierden los beneficios de caché. Olvidé mencionar que mi máquina tiene paquetes duales de CPU de cuatro núcleos. Intuitivamente, si hay una cola compartida entre dos subprocesos programados en los dos CPU _packages_, el rendimiento será abismal. Pero, esto es solo una suposición, de ahí la pregunta. :) – Matt
Ya veo. Ahora que lo mencionas, recuerdo haber rellenado deliberadamente un objeto de comunicación entre subprocesos para garantizar que dos instancias no pudieran estar en la misma línea de caché. Supongo que las cosas se ponen aún más sombrías si están involucrados dos paquetes discretos :( –
Sí, no sé cuántos datos hay en las clases entre cadenas/struct/lo que sea, pero puedes crear un conjunto de ellos al inicio, asegurándote de que su tamaño/s es, por ejemplo, 4k y en un límite de página, lo que debería reducir el enjuague de caché, ya que no es necesario que dos núcleos tengan que operar en la misma página de datos. –