2012-02-07 45 views
7

Supongamos que tenemos una cantidad fija de trabajo de cálculo, sin bloqueo, inactividad, espera de E/S. El trabajo se puede paralelizar muy bien: consiste en tareas de cálculo pequeñas e independientes de 100M.¿Cómo hacer los mismos cálculos más rápido en la CPU de 4 núcleos: 4 hilos o 50 hilos?

¿Qué es más rápido para la CPU de 4 núcleos: para ejecutar 4 hilos o ... digamos 50? ¿Por qué la segunda variante debería ser slover y cuánto slover?

Como supongo: cuando ejecuta 4 hilos pesados ​​en la CPU de 4 núcleos sin otro proceso/hilos que consumen CPU, el planificador no puede mover los hilos entre los núcleos en absoluto; no tiene ninguna razón para hacer eso en esta situación. Core0 (CPU principal) será responsable de ejecutar el controlador de interrupción para el temporizador de hardware 250 veces por segundo (configuración básica de Linux) y otros controladores de interrupción de hardware, pero puede que otros núcleos no sientan ninguna preocupación.

¿Cuál es el costo del cambio de contexto? ¿El tiempo para almacenar y restaurar registros de la CPU para diferentes contextos? ¿Qué hay de los cachés, las tuberías y varias cosas de predicción de código dentro de la CPU? ¿Podemos decir que cada vez que cambiamos de contexto, dañamos cachés, tuberías y algunas instalaciones de decodificación de código en la CPU? Entonces, ¿hay más hilos ejecutándose en un único núcleo, menos trabajo que puedan hacer juntos en comparación con su ejecución en serie?

La pregunta sobre caches y otra optimización de hardware en entornos de subprocesamiento múltiple es la pregunta interesante para mí ahora.

+3

La respuesta es muy aplicación-, system y específico del equipo. Pero probablemente sea más grande que 4, pero mucho menos de 50 hilos. ¿Intentó medir con 4, 6, 8, 10 hilos? –

+0

4 hilos (o 8 w/subprocesamiento Hyper). Menos porciones de datos. mejores propiedades de caché. – bestsss

Respuesta

11

Como @Baile menciona en los comentarios, esto es altamente de aplicación, sistema, entorno específico.

Y como tal, no voy a tomar el enfoque de línea dura de mencionar exactamente 1 hilo para cada núcleo. (o 2 subprocesos/núcleo en el caso de Hyperthreading)

Como experimentado programador de memoria compartida, he visto por experiencia que el número óptimo de subprocesos (para una máquina de 4 núcleos) puede oscilar entre 1 y 64 +.

Ahora voy a enumerar las situaciones que pueden causar este rango:

Optimal Hilos < # de núcleos

En ciertas tareas que son de grano fino muy paralelo (como pequeñas FFT), la sobrecarga de enhebrado es el factor de rendimiento dominante. En algunos casos, no es útil paralizar en absoluto. En algunos casos, obtienes aceleración con 2 subprocesos, pero escalando hacia atrás en 4 subprocesos.

Otro problema es la contención de recursos. Incluso si tiene una tarea altamente paralelizable que puede dividirse fácilmente en 4 núcleos/hilos, puede verse embotellado por el ancho de banda de memoria y los efectos de caché. Muy a menudo, encuentra que 2 hilos serán tan rápidos como 4 hilos.(Como si a menudo el caso con muy grandes FFT)

óptimas Hilos = # de Núcleos de

Este es el caso óptimo. No hay necesidad de explicar aquí, un hilo por núcleo. La mayoría de las aplicaciones vergonzosamente paralelas que no son de memoria o E/S encajan aquí.

Optimal Temas> # de núcleos

Aquí es donde se pone interesante ... muy interesante. ¿Has oído hablar de desequilibrio de carga? ¿Qué tal la descomposición excesiva y el robo de trabajo?

Muchas aplicaciones paralelizables son irregulares, lo que significa que las tareas no se dividen en subtareas de igual tamaño. Entonces, si puede terminar dividiendo una tarea grande en 4 tamaños desiguales, asígnelos a 4 hilos y ejecútelos en 4 núcleos ... ¿el resultado? Pobre rendimiento paralelo porque 1 hilo pasó a tener 10 veces más trabajo que los otros hilos.

Una solución común aquí es sobre descomponer tarea en muchas subtareas. Puede crear subprocesos para cada uno de ellos (de modo que ahora obtiene hilos >>núcleos). O puede usar algún tipo de planificador de tareas con un número fijo de hilos. No todas las tareas son adecuadas para ambos, por lo que con bastante frecuencia, el enfoque de sobredescomposición de una tarea a 8 o 16 hilos para una máquina de 4 núcleos ofrece resultados óptimos.


Aunque el engendrar más hilos puede conducir a un mejor balance de carga, la sobrecarga se acumula. Por lo general, hay un punto óptimo en alguna parte. He visto hasta 64 hilos en 4 núcleos. Pero como se mencionó, es altamente específico de la aplicación. Y necesitas experimentar


EDIT: La expansión de respuesta a más directamente responder a la pregunta ...

¿Cuál es el costo de cambio de contexto? El tiempo para almacenar y restaurar registros de CPU para contexto diferente?

Esto es muy dependiente del medio ambiente, y es algo difícil de medir directamente.
Respuesta corta: Muy CaroThis might be a good read.

¿Qué hay de cachés, tuberías y varias cosas en código de predicción dentro CPU? ¿Podemos decir que cada vez que cambiamos de contexto, dañamos las cachés, las tuberías y algunas instalaciones de decodificación de código en la CPU?

Respuesta corta: Sí cuando se cambio de contexto a cabo, es probable que limpiar su tubería y estropear todos los predictores. Lo mismo con cachés Es probable que el nuevo hilo reemplace el caché con nuevos datos.

Aunque hay una trampa. En algunas aplicaciones donde los subprocesos comparten los mismos datos, es posible que un subproceso pueda potencialmente "calentar" el caché para otro subproceso entrante u otro subproceso en un núcleo diferente que comparte el mismo caché.(Aunque es raro, he visto que esto suceda antes en una de mis máquinas NUMA - superlinear speedup:!?!?! 17.6x a través de 16 núcleos)

Así que más subprocesos que se ejecutan en un solo núcleo, menos trabajo que puede hacer juntos en comparación con su ejecución en serie?

Depende, depende ... Aparte de la hiperversión, sin duda habrá una sobrecarga. Pero he leído un artículo en el que alguien utiliza un segundo hilo para precargar el hilo principal ... Sí que es una locura ...

+0

si tiene 1OOM tareas pequeñas, hilos = núcleos parece obvio y en el peor de los casos + robo de trabajo. sin embargo, una publicación encantadora. – bestsss

+0

De hecho, es poco probable que las tareas pequeñas de 100M sean óptimas en el caso de subprocesos> núcleos (salvo HyperThreading). Según la cantidad de recursos que tenga, incluso puede caer en la categoría de subprocesos núcleos es muy común en situaciones en las que tiene una tarea que se divide en, por ejemplo, 6 partes iguales, pero solo tiene 4 núcleos ... – Mysticial

0

Si puede usar 4 hilos, úselos. No hay forma de que 50 salgan más rápido que 4 en una máquina de 4 núcleos. Todo lo que obtienes es más sobrecargado.

Por supuesto, usted está describiendo una situación ideal que no es del mundo real, así que sea lo que sea que realmente está construyendo, necesitará medir para comprender cómo se ve afectado el rendimiento.

0

Hay tecnología Hyperthreading que puede manejar más de un hilo por CPU, pero no depende del tipo de cálculo que desee realizar. Considere el uso de una GPU o un lenguaje de ensamblaje muy bajo para lograr la máxima potencia.

0

Creación de 50 hilos en realidad perjudicará el rendimiento, lo mejora. Simplemente no tiene ningún sentido.

Lo ideal sería que usted debe hacer el 4 hilos, no más, no menos. Habrá algunos gastos generales debido al cambio de contexto, pero eso es inevitable. Los hilos de SO/servicios/otras aplicaciones también deberían ejecutarse. Pero hoy en día, con CPUs tan potentes y rápidas, esto no tiene importancia, ya que esos hilos del sistema operativo solo necesitarán menos del 2% del tiempo de la CPU. Casi todos estarán en estado bloqueado mientras tu programa se está ejecutando.

Se podría pensar que, ya que el rendimiento es de importancia crítica, debe codificar esas pequeñas áreas críticas en lenguaje ensamblador de bajo nivel. Los lenguajes de programación modernos lo permiten.

Pero en serio ... los compiladores y, en el caso de Java, la JVM, optimizarán esas porciones tan bien que simplemente no vale la pena (a menos que realmente desee ejercer algo como esto). En lugar de que sus cálculos terminen en 100 segundos, terminarán en 97 o 98. La pregunta que debe hacerse es: ¿vale la pena todas esas horas de codificación y depuración?

Se le preguntó sobre el costo de tiempo de cambio de contexto. En estos días, estos son extremadamente bajos. Mire las CPU modernas de doble núcleo que ejecutan Windows 7, por ejemplo. Si inicia un servidor web Apache en esa máquina y un servidor de base de datos MySQL, podrá acceder fácilmente a más de 800 subprocesos. La máquina simplemente no lo siente. Para ver qué tan bajo es este costo, lea aquí: How to estimate the thread context switching overhead?. Para ahorrarle la parte de búsqueda/lectura: el cambio de contexto se puede hacer cientos de miles de veces por segundo.

+0

* Si inicia un servidor web Apache en esa máquina y un servidor de base de datos MySQL, fácilmente pasará de 800 hilos. * pero casi todos están inactivos (es decir, no hay cambio de contexto) – bestsss

0

4 hilos son más rápidos si se puede programar sus tareas de conmutación 40 mejor que el sistema operativo.

Cuestiones relacionadas