test resuelve procesos manejo los ingenieria identificar evitar empresa cómo cuello como botella administracion c multithreading performance memory

resuelve - evitar cuello de botella en red



¿Cómo comprobar si el ancho de banda de la memoria se ha convertido en un cuello de botella? (3)

+1 para una buena pregunta.

Primero quiero decir que hay otros factores a tener en cuenta, como la sincronización de la memoria caché o la parte de serialización inevitable como las operaciones de memoria atómica, que también son posibles cuellos de botella y más fáciles de verificar que el ancho de banda de la memoria.

En cuanto al ancho de banda de memoria, lo que estoy teniendo ahora es una idea ingenua que consiste en lanzar un daemon simple para consumir el ancho de banda de la memoria mientras perfila su aplicación, simplemente repitiendo el acceso a la memoria principal (asegúrese de considerar la existencia de caché). Con el daemon puede ajustar y registrar el ancho de banda de memoria que consume y comparar este resultado con el rendimiento de su aplicación.

Perdón por proporcionar una respuesta tan descuidada ... aunque es posible XD

EDITADO: Ver también Cómo medir el ancho de banda de memoria que se está utilizando actualmente en Linux? y ¿cómo puedo observar el ancho de banda de la memoria?

Estoy trabajando en un programa C muy concurrente, se escala bien cuando el número de núcleos es menor que 8, pero se niega a escalar más allá de 8 núcleos.

Sospecho que el ancho de banda de la memoria es el cuello de botella, ¿cómo puedo verificar si eso es cierto?

¿Hay alguna herramienta / técnica / función del sistema operativo que pueda ayudar con el diagnóstico?


He tenido este problema yo mismo en una máquina de núcleos NUMA 96x8.

El 90% del tiempo el problema es con la sincronización de memoria / caché. Si llama frecuentemente a las rutinas de sincronización (atómicas, mutex), la línea de caché apropiada debe invalidarse en todos los sockets, lo que conduce a un bloqueo completo de todo el bus de memoria para varios ciclos.

Puede perfilar esto ejecutando un generador de perfiles como Intel VTune o Perfsuite y Perfsuite que registren cuánto tiempo toman sus átomos. Si los está utilizando correctamente, deben tomar algo entre 10-40 ciclos. El peor escenario que tuve fue de 300 ciclos al escalar mi aplicación multiproceso a 8 sockets (8x8 núcleos en Intel Xeon).

Otro paso sencillo de creación de perfiles que puede hacer es compilar sin átomos atómicos / exclusiones mutuas (si su código lo permite) y ejecutarlo en varios sockets: debería ejecutarse rápidamente (incorrecto, pero rápido).

La razón por la que su código se ejecuta rápidamente en 8 núcleos se debe a que los procesadores Intel están usando el bloqueo de caché cuando ejecutan atómicos, siempre y cuando se mantenga todo en el mismo chip físico (socket). Si un bloqueo tiene que ir al bus de memoria, aquí es cuando las cosas se ponen feas.

Lo único que puedo sugerir es: reducir la cantidad de veces que llamas rutinas atómicas / sincronización.

En cuanto a mi aplicación: tuve que implementar una estructura de datos prácticamente sin bloqueo para escalar mi código más allá de un socket. Cada hilo acumula acciones que requieren un bloqueo y verifica regularmente que es su turno de enjuagarlas. Luego pase un token y tome turnos para enjuagar las acciones de sincronización. Obviamente, solo funciona si tiene suficiente trabajo que hacer mientras espera.


Si bien sería útil tener más información sobre el algoritmo y la plataforma, en general hay una serie de razones por las que una aplicación no se escala:

  1. Uso de sincronización explícita (mutexes / atomics / transactions, etc.): la sincronización en un programa paralelo significa que usted crea algunas secciones secuenciales cuando tiene que compartir un recurso entre múltiples hilos. Cuantos más subprocesos quieren acceder a la sección crítica (una operación atómica es realmente una sección crítica muy pequeña), mayor es la contención que tiene y más limitada es su escalabilidad, ya que los núcleos se están convirtiendo en la sección crítica. Reducir el tamaño de las secciones críticas y elegir diferentes estructuras / algoritmos de datos puede mitigar eso si no es posible privatizar el recurso.

  2. Uso compartido falso: dos o más subprocesos que comparten objetos no relacionados que terminan en el mismo bloque de caché. Normalmente es fácil de detectar al ver un aumento en las fallas de caché a medida que escala su aplicación de un núcleo a más y de un socket a más de un socket. Alinear sus estructuras de datos al tamaño del bloque de caché generalmente lo resuelve. Consulte también Eliminar la participación falsa: Dr Dobb''s

  3. Asignación / desasignación de memoria: mientras que la asignación de memoria le proporcionará trozos de memoria para que los diferentes funcionen, puede tener contención en la asignación o incluso en la desasignación. Puede resolverse utilizando un asignador de memoria escalable seguro para subprocesos como el asignador escalable de Intel TBB , Hoard y otros.

  4. Hilos inactivos: ¿su algoritmo tiene un patrón productor / consumidor y podría ser que usted está consumiendo más rápido de lo que produce? ¿Su tamaño de datos es lo suficientemente grande como para amortizar el costo de la paralelización y no perder velocidad al perder la localidad? ¿Su algoritmo es indescifrable por alguna otra razón? Probablemente tengas que decirnos algo más sobre tu plataforma y tu algoritmo. Intel Advisor es una herramienta decente para verificar cuál es la mejor forma de paralelizar.

  5. Marco paralelo: ¿qué estás usando? OpenMP, Intel TBB, ¿algo más? ¿Hilos puros? ¿Tal vez te bifurcas demasiado o sobrepartes tu problema? ¿Tu tiempo de ejecución es escalable?

  6. Otros motivos técnicos: enlace incorrecto de subprocesos a núcleos (tal vez múltiples subprocesos terminan en el mismo núcleo), características del tiempo de ejecución paralelo (el tiempo de ejecución OpenMP de Intel tiene un subproceso oculto adicional, el enlazado de subprocesos puede correlacionar este subproceso adicional en el mismo núcleo como el hilo principal, arruinando tu día) etc.

Desde mi experiencia, me parece que una vez que eliminaste todo lo anterior, puedes comenzar a sospechar del ancho de banda de la memoria. Puede verificarlo fácilmente con STREAM que puede decirle si su ancho de banda de memoria es el factor limitante. Existe este article en el sitio web de Intel que explica cómo detectar la saturación de ancho de banda de memoria.

Si ninguno de los anteriores es concluyente, es posible que tenga una escalabilidad limitada mediante el tráfico de protocolo de coherencia y / o NUMA (acceso a memoria no uniforme, un buen artículo en acmqueue ). Cada vez que accede a algún objeto en la memoria, genera solicitudes de invalidación de caché (está compartiendo algo y se activa el protocolo de coherencia de caché) o accede a la memoria que vive en un banco más cercano a otro socket (está atravesando la interconexión del procesador) )