Azure Native Qumulo ahora disponible en la UE, el Reino Unido y Canadá: Más información

El rendimiento de acceso a memoria no uniforme (NUMA) es una situación MESI

Escrito por:

"Nu mă, nu mă iei"
- Dan Mihai Bălan

Como sabrá cualquiera que haya administrado un sistema de archivos Linux anteriormente, la actualización a una nueva versión del kernel de Linux no suele ser demasiado difícil, pero a veces puede tener un impacto sorprendente en el rendimiento. Esta es una historia de una de esas épocas.

De qumulo software del sistema de archivos se envía sobre una distribución de Ubuntu bastante estándar. Actualizamos periódicamente la distribución y el kernel de Linux subyacente para mantenernos en las versiones compatibles a largo plazo, de modo que podamos seguir estando al tanto de las últimas actualizaciones de seguridad y correcciones de errores, así como para admitir dispositivos de almacenamiento más nuevos.

Recientemente actualizamos todas nuestras plataformas para usar Linux 5.4; anteriormente, algunas estaban en 4.4 y otras en 4.15. En su mayor parte, todo salió bien. Pero en las pruebas de rendimiento con el nuevo kernel, notamos algo extraño: el rendimiento de nuestros sistemas Qumulo con CPU Intel dual 4U (conocidos por nuestros clientes como los sistemas Qumulo QC104, QC208, QC260 y QC360) había disminuido, mucho. En una prueba con una gran cantidad de flujos de escritura, el rendimiento pasó de ~ 4.5 GB / s a ​​aproximadamente 3.2 GB / s, ¡casi una caída del 30%!

Estos sistemas utilizan un Haswell de doble procesador. Muchos de nuestros clientes tienen implementaciones grandes y activas de las que dependen para administrar sus datos, y trabajamos constantemente para que nuestras plataformas sean más rápidas con el tiempo, ¡no más lentas!

Así que era hora de investigar, averiguar qué había hecho que nuestro software se ejecutara más lento y solucionarlo.

Supervisión, resolución de problemas y diagnóstico de problemas de rendimiento de Linux

Al diagnosticar cualquier tipo de problema de rendimiento, por lo general, comenzamos mirando los contadores de rendimiento, las mediciones de latencia y otras métricas generadas por la instrumentación dentro de nuestro sistema de archivos. Las herramientas de supervisión del rendimiento de Linux como estas nos permiten analizar fácilmente dónde pasa el tiempo el sistema y diagnosticar con mayor precisión la fuente del problema. En este caso, las métricas contaron una historia clara: la E / S del disco era normal, el uso de la CPU era normal, pero se dedicaba mucho más tiempo a las redes.

Esto nos llevó a buscar más de cerca cualquier cosa relacionada con la red que pudiera haber cambiado significativamente como parte de la actualización. Afortunadamente, nos ahorramos la tarea de buscar en el código del kernel, ya que encontramos un sospechoso principal de inmediato: además de actualizar a Linux 5.4, habíamos cambiado los controladores de Ethernet. Anteriormente, usábamos OFED para las NIC de Mellanox, pero ahora usábamos la versión incluida con el kernel.

Los detalles del código del controlador tampoco resultaron ser importantes, ya que la causa real de la degradación del rendimiento fue un pequeño cambio de configuración: OFED incluye un script que afinita automáticamente las interrupciones de red con la CPU más cercana, el controlador en caja no. Reintroducir el script, o simplemente establecer las afinidades manualmente, devolvió inmediatamente todo el rendimiento.

Entonces, teníamos nuestra respuesta, y con un pequeño ajuste pudimos enviar con confianza la nueva distribución con kernel 5.4 a nuestros clientes.

Solución de problemas de un cuello de botella de rendimiento relacionado con NUMA

No estamos satisfechos con simplemente poder solucionar problemas. Queremos entender sus causas subyacentes. Y en este caso, algo parecía extraño. En un sistema NUMA (sistema de acceso a memoria no uniforme), generalmente es mejor tener las interrupciones afinizadas localmente, pero en los niveles de rendimiento en consideración (solo un par de GB / s en un nodo determinado) no tenía sentido que la comunicación entre las CPU podrían ser el cuello de botella.

El siguiente diagrama muestra una imagen simplificada de la arquitectura. Tiene dos CPU Xeon E5-2620 v3, 128 GB de RAM y varios discos:

 

Tenga en cuenta los vínculos entre las dos CPU. Estos son canales de interconexión QuickPath (QPI), que se utilizan siempre que una CPU necesita datos que solo están disponibles para la otra CPU; por ejemplo, si la CPU 1 necesita procesar datos que se recibieron de la red, los datos deberán cruzar QPI .

[tipo de cuadro = "sombra"]¿Qué es QuickPath Interconnect?

QuickPath Interconnect es una conexión de datos entre una CPU y otros recursos de la placa base (como un concentrador de E/S u otras CPU) en algunas microarquitecturas de Intel, introducida por primera vez en 2008. Su objetivo es proporcionar un ancho de banda extremadamente alto para permitir una alta escalabilidad integrada, después de En resumen, no tiene sentido poner más CPU en una placa base si no pueden hacer un uso completo de los recursos del sistema. (Fue reemplazada en 2017 por una nueva versión, llamada UltraPath Interconnect, con el lanzamiento de la microarquitectura Skylake).[/box]

El E5-2620 v3 tiene dos canales de interconexión QuickPath de 16 bits cronometrado a 4GHz. Cada canal transfiere datos tanto en flancos de reloj ascendentes como descendentes, lo que da como resultado 8 gigatransferencias (GT) por segundo, o 16 GB / s de ancho de banda en ambas direcciones. Entonces, con dos de ellos, deberíamos acercarnos a los 32 GB / s antes de que este enlace se convierta en un cuello de botella, ¡más que suficiente para manejar los requisitos relativamente modestos de la NIC y los dispositivos de almacenamiento!

Sin embargo, claramente, estábamos experimentando un cuello de botella y desapareció cuando tomamos medidas para evitar la comunicación entre CPU. Entonces, ¿qué estaba pasando?

Echemos un vistazo a lo que debe suceder cuando un nodo de Qumulo procesa una solicitud para leer datos, digamos usando el protocolo NFS. El siguiente diagrama muestra una versión simplificada del flujo de datos:

 

  1. Algunos datos deberán obtenerse de otros nodos (la flecha azul). Estos datos llegan como una serie de segmentos TCP a la NIC, que luego se descargan a través de DMA a los búferes de anillo en el kernel, y desde allí al búfer de página interno del sistema de archivos Qumulo.
  2. Se obtendrán algunos datos de este nodo (flecha violeta). Esto se lee del disco y se copia en el búfer de la página.
  3. Una vez que se han recopilado los datos locales y los datos remotos, un trabajador de protocolo lo ensambla todo en una respuesta, que luego se coloca en búferes de transmisión, desde los cuales se enviará DMA a la NIC y se enviará a través de la red al cliente solicitante. .

Llegar al centro de la cebolla

Una idea clave aquí es que cada una de las flechas en el diagrama de flujo anterior (excepto las que salen de la NIC) representan un punto donde sería posible que los datos crucen el enlace QPI, a veces más de una vez.

Por ejemplo, recuerde del diagrama de arquitectura que hay dispositivos de almacenamiento conectados a ambas CPU. Si la CPU 0 lee 1 GB de datos de un disco conectado a la CPU 1 y luego lo copia en una región del búfer de página asignada a la memoria adjunta a la CPU 1, esos datos cruzarán el enlace dos veces. El trabajador de protocolo que procesa los datos puede ejecutarse en la CPU 0, requiriendo los mismos datos para cruzar el enlace nuevamente, y así sucesivamente.

Por lo tanto, hay un "efecto de amplificación" en juego: aunque el nodo puede estar entregando datos a solo 2 GB / s, podría haber varias veces más tráfico en la interconexión QuickPath, debido a que los mismos datos rebotan hacia adelante y hacia atrás, como un juego de tenis de datos:

 

Identificar al verdadero culpable del cuello de botella de rendimiento relacionado con NUMA

¡Pero espera, te escucho decir! Incluso en los escenarios más pesimistas, esta amplificación no podría convertir 2 GB / s en 32 GB / s, ¡simplemente no hay suficientes bordes que crucen el límite de NUMA en ese gráfico!

Eso es cierto: parecía que nos estábamos enfrentando a un cuello de botella muy por debajo de la velocidad nominal del enlace. Afortunadamente, Intel Comprobador de latencia de memoria (también conocido como Intel MLC) puede medir el rendimiento real del sistema directamente, así que lo ejecutamos y confirmó nuestras sospechas:

Measuring Memory Bandwidths between nodes within system
Bandwidths are in MB/sec (1 MB/sec = 1,000,000 Bytes/sec)
Using all the threads from each core if Hyper-threading is enabled
Using Read-only traffic type
            Numa node
Numa node        0         1
       0    46242.9          6291.7
       1     6276.3         46268.6</var/www/wordpress>

La CPU 0 podía acceder a su RAM conectada directamente a ~ 46 GB / s, y lo mismo para la CPU 1, pero en el momento en que cualquiera de ellos quería acceder a la memoria conectada a la otra CPU, lo mejor que podían hacer era 6 GB / s. .

En este punto, si está muy familiarizado con la arquitectura Haswell de Intel, es posible que ya sepa lo que está sucediendo. No lo éramos especialmente, así que recurrimos a buscar en Google los síntomas, y eso es lo que nos llevó a la respuesta correcta, en un Hilo de la comunidad Intel. Simplemente ingrese al BIOS, cambie el "modo de búsqueda" de "búsqueda temprana" a "búsqueda casera", ¡y el cuello de botella desaparece!

Entonces, ¿qué diablos es un fisgón temprano? Desafortunadamente, el snoop temprano no tiene nada que ver con un beagle de dibujos animados o con cierto rapero estadounidense tomando su taza de café por la mañana. En cambio, tendremos que hablar sobre uno de los dos problemas más difíciles de la informática: coherencia de caché. (Los otros dos son nombres de cosas y errores de uno por uno). Las cosas están a punto de obtener MESI. Específicamente, el espionaje es parte del protocolo MESI y, por extensión, la variante MESIF utilizada por los procesadores Intel.

El protocolo de coherencia de caché de MESI

MESI es un protocolo común para hacer cumplir la coherencia de la memoria caché, es decir, que todas las diferentes memorias caché del sistema tengan una vista coherente del contenido de la memoria. MESI funciona asignando uno de los cuatro estados a cada línea en cada caché, lo que determina cómo se puede usar esa línea de caché:

  • Modificado: la línea ha sido cambiada y ya no coincide con lo que está en la memoria principal.
  • Exclusiva: la línea coincide con la memoria principal y solo está presente en este caché.
  • Compartido: la línea no está modificada, pero puede estar presente en otras cachés.
  • Inválido: la línea no se utiliza o se ha invalidado (por ejemplo, porque se modifica la copia de otra caché).

MESI vs.MESIF

MESIF es una extensión de MESI que fue desarrollada por Intel. Agrega un quinto estado, F para "adelante". Reenviar es similar a Compartido, pero solo una caché del sistema puede tener una línea en el estado Reenviar. Esto es principalmente una optimización para evitar un exceso de respuestas cuando se solicita una línea de caché del sistema. En lugar de que responda cada caché que contiene una copia de la línea, solo responderá la caché que contiene la línea en el estado F.

Tanto en MESI como en MESIF, las diversas cachés se mantienen coherentes mediante notificaciones a través del bus cuando ocurren cambios importantes; por ejemplo, si se escribe una línea en una caché, cualquier otra caché con una copia debe tener esa copia invalidada.

Early Snoop vs Home Snoop

La razón por la que esta consideración es fundamental para el rendimiento tiene que ver con el diseño de las cachés en la arquitectura Haswell de Intel. La caché compartida de último nivel (LLC) de cada paquete se divide en varios segmentos, uno por núcleo, conectados a un anillo en matriz de ancho de banda muy alto. Cada segmento de caché tiene su propio "agente" de caché. También hay un "agente doméstico" para cada controlador de memoria:

 

En el modo de "rastreo temprano" (mostrado arriba, con dos CPU), cuando ocurre un evento de falta de caché o coherencia de caché, el agente de caché iniciador transmitirá un mensaje a todos los demás agentes de caché en el sistema. Esto tiene como objetivo reducir la latencia de acceso al reducir el tiempo necesario para establecer el estado de una línea de caché, pero con todos los agentes de caché en la CPU remota respondiendo a través de QuickPath Interconnect, la charla de coherencia puede reducir significativamente el ancho de banda de memoria entre nodos disponible. Aparentemente, con Haswell-EP E5-2620 v3, es suficiente perder el 75% de su ancho de banda.

Por el contrario, en el modo "snoop doméstico", los mensajes son manejados primero por los agentes domésticos en cada controlador de memoria y luego delegados a los agentes LLC según sea necesario. El salto adicional agrega una pequeña cantidad de latencia, pero con el beneficio de un rendimiento mucho mayor. Tenga en cuenta que se envían muchos menos mensajes a través de QuickPath Interconnect:

 

See esta publicación para una explicación más profunda de la coherencia de la caché NUMA.

Entonces, ¿cuánto mejor es el fisgón hogareño?

Con el modo snoop cambiado en todas las máquinas de nuestro clúster de prueba, Memory Latency Checker mostró un rendimiento drásticamente mejorado entre las CPU:

Measuring Memory Bandwidths between nodes within system
Bandwidths are in MB/sec (1 MB/sec = 1,000,000 Bytes/sec)
Using all the threads from each core if Hyper-threading is enabled
Using Read-only traffic type
            Numa node
Numa node         0          1
       0     45139.0    25323.8
       1     25336.2    45021.7</var/www/wordpress>

Pero mejor aún, aliviar este cuello de botella también mejoró significativamente el rendimiento de estos sistemas: no solo eliminó la regresión del 30% observada cuando se perdió la afinidad de interrupción, sino que agregó otro 30% de rendimiento adicional:

Prueba (4 nodos, QC208) Línea de base (fisgoneo temprano) Inicio snoop Cambios
Rendimiento de escritura 4400 MB / 6000 MB / + 36%
Rendimiento de lectura 7650 MB / s 9550 MB / s / s + 29%

Recuerdo que por primera vez resolví problemas de rendimiento en esta plataforma hace cinco o seis años, muy temprano en mi carrera en Qumulo, y tengo un vago recuerdo de que experimentamos con el modo Snoop en ese entonces. En ese momento, no hizo mucha diferencia. Pero a lo largo de los años, a medida que continuamos mejorando el rendimiento al eliminar los cuellos de botella del software, el rendimiento de la plataforma de hardware subyacente se convirtió en el factor limitante, por lo que aumentar el límite de rendimiento de QuickPath Interconnect se convirtió en una gran victoria.

Entonces, en la próxima versión de Qumulo Core, agregamos código para cambiar esta configuración en el BIOS para todos los modelos afectados, de modo que todos nuestros clientes con implementaciones existentes se beneficien de una mayor capacidad de rendimiento.

Se está haciendo mucho más trabajo en Qumulo para mejorar el rendimiento de nuestro sistema de archivos. La mayor parte es mucho más difícil (e incluso más interesante) que encontrar un interruptor oculto de "ir rápido", ¡así que sigue mirando este espacio!

¿Interesado en aprender más sobre ingeniería en Qumulo? Ver más publicaciones escritas por ingenieros de Qumulo, esta página. Alternativamente, eche un vistazo a Plataforma de datos Qumulo: descripción general de la arquitectura de software (PDF).


OTRAS LECTURAS

Artículos Relacionados

Ir al Inicio