Número óptimo de hilos por núcleo


281

Digamos que tengo una CPU de 4 núcleos y quiero ejecutar algún proceso en el mínimo tiempo posible. El proceso es idealmente paralelo, por lo que puedo ejecutar fragmentos de él en un número infinito de hilos y cada hilo lleva la misma cantidad de tiempo.

Como tengo 4 núcleos, no espero ninguna aceleración ejecutando más subprocesos que núcleos, ya que un solo núcleo solo es capaz de ejecutar un único subproceso en un momento dado. No sé mucho sobre hardware, así que esto es solo una suposición.

¿Hay algún beneficio en ejecutar un proceso paralelo en más hilos que núcleos? En otras palabras, ¿mi proceso finalizará más rápido, más lento o aproximadamente en la misma cantidad de tiempo si lo ejecuto usando 4000 hilos en lugar de 4 hilos?

Respuestas:


254

Si sus hilos no hacen E / S, sincronización, etc., y no hay nada más en ejecución, 1 hilo por núcleo le proporcionará el mejor rendimiento. Sin embargo, muy probablemente no sea el caso. Agregar más subprocesos generalmente ayuda, pero después de algún punto, causan una cierta degradación del rendimiento.

No hace mucho tiempo, estaba haciendo pruebas de rendimiento en una máquina de 2 núcleos cuádruples con una aplicación ASP.NET en Mono bajo una carga bastante decente. Jugamos con el número mínimo y máximo de subprocesos y al final descubrimos que para esa aplicación en particular en esa configuración en particular, el mejor rendimiento era entre 36 y 40 subprocesos. Cualquier cosa fuera de esos límites funcionó peor. ¿Lección aprendida? Si yo fuera usted, probaría con diferentes hilos hasta que encuentre el número correcto para su aplicación.

Una cosa es segura: 4k hilos tardarán más. Eso es un montón de cambios de contexto.


21
Creo que la respuesta de Gonzalo es buena. Solo agregaría que debes experimentar y medir. Su programa será diferente al suyo, el mío o el de cualquier otra persona y solo las mediciones del comportamiento de su propio programa responderán sus preguntas correctamente. El desempeño de los programas paralelos (o concurrentes) no es un área donde se puedan sacar buenas conclusiones solo de los primeros principios.
Alto rendimiento Mark

55
+1, + respuesta: me sorprende que tener muchos más hilos que núcleos resulte en un mejor rendimiento, aunque tiene sentido si más hilos significan una mayor porción de tiempo en comparación con los hilos de la competencia. Sería bueno que mi aplicación pudiera detectar diferencias en el rendimiento y sintonizarse automáticamente con el número óptimo de subprocesos.
Julieta el

12
No debería sorprenderte en un escenario del mundo real. Los subprocesos bloquean la espera de recursos IO como acceso a disco, red, etc. Y también esperan que los recursos que no son IO como otros subprocesos terminen de usar variables compartidas. Lo que realmente desea lograr es el número mínimo de subprocesos, de modo que siempre se pueda ejecutar al menos un subproceso por núcleo.
patros

44
1 hilo por núcleo no es lo óptimo. Debe ser un poco más, preferiblemente el doble, ya que esto permitirá que se ejecute otro subproceso si un subproceso se bloquea temporalmente. Incluso si solo en la memoria. Esto es más importante si tiene sistemas (P4, I7, Sun Rock, etc.) que cuentan con SMT / HT
Marco van de Voort

1
De ahí el "Es muy probable que ese no sea el caso" en mi respuesta. Encontrar el número correcto depende de la aplicación y la arquitectura en la que se ejecuta.
Gonzalo

129

Estoy de acuerdo con la respuesta de @ Gonzalo. Tengo un proceso que no hace E / S, y esto es lo que he encontrado:

ingrese la descripción de la imagen aquí

Tenga en cuenta que todos los subprocesos funcionan en una matriz pero diferentes rangos (dos subprocesos no acceden al mismo índice), por lo que los resultados pueden diferir si han trabajado en diferentes matrices.

La máquina 1.86 es una MacBook Air con un SSD. El otro mac es un iMac con un HDD normal (creo que es 7200 rpm). La máquina de Windows también tiene un disco duro de 7200 rpm.

En esta prueba, el número óptimo era igual al número de núcleos en la máquina.


14
+1 para el gráfico. Claramente, 1 hilo por núcleo es lo mejor, pero es interesante que el sistema de cuatro núcleos parece no tener números de hilo más altos (<100 de todos modos) como lo hacen los demás.
Jim Garrison

46
-1 para el gráfico! ¿Curvas suaves a través de coordenadas x con valores enteros? ¿Un salto salvaje de 1 2 3 a 10 20 30 a 50 100? Y coordenadas y que son múltiplos de 10 más 2 para una buena medida. Esto es lo que hace Excel, ¿no?
Spacedman

55
@Spacedman Sí, lo es. Las curvas suaves tienen un aspecto mucho más bonito en mi humilde opinión. : D
Motasim

22
@PascalvKooten, El problema no es que se vea bonito, es engañoso a primera vista. En primer lugar, el eje y comienza en 42, exagerando la aparente diferencia entre las máquinas probadas. En segundo lugar, la extraña progresión de los valores del eje x sugiere que 'tiempo tomado' no se escala linealmente con 'número de hilos', esto es especialmente cierto para la línea azul. Creo que el problema que otros (incluido yo mismo) tenemos es que tergiversa los datos.
pauluss86

13
@Spacedman La crítica en el gráfico es lo más ridículo que he encontrado en las últimas 24 horas. El gráfico ayuda. Mucho. Período. ¿Podría haberse hecho mejor? A nadie le importa. ¿Curva suave en lugar de discreta? ¿¿¿¿Este es tu problema???? Supongo que todos ustedes nunca incluirían un gráfico de este tipo en su respuesta porque no tienen el tiempo / energía extra para que se vea bien. Ese es mi punto.
tyrex

50

Sé que esta pregunta es bastante antigua, pero las cosas han evolucionado desde 2009.

Ahora hay dos cosas a tener en cuenta: la cantidad de núcleos y la cantidad de hilos que pueden ejecutarse dentro de cada núcleo.

Con los procesadores Intel, el número de subprocesos está definido por Hyperthreading, que es solo 2 (cuando está disponible). ¡Pero Hyperthreading reduce su tiempo de ejecución en dos, incluso cuando no usa 2 hilos! (es decir, 1 canalización compartida entre dos procesos; esto es bueno cuando tiene más procesos, de lo contrario no es tan bueno. ¡Más núcleos son definitivamente mejores!)

En otros procesadores, puede tener 2, 4 o incluso 8 hilos. Entonces, si tiene 8 núcleos, cada uno de los cuales admite 8 subprocesos, podría tener 64 procesos ejecutándose en paralelo sin cambio de contexto.

"Sin cambio de contexto" obviamente no es cierto si se ejecuta con un sistema operativo estándar que hará el cambio de contexto para todo tipo de otras cosas fuera de su control. Pero esa es la idea principal. ¡Algunos sistemas operativos le permiten asignar procesadores para que solo su aplicación tenga acceso / uso de dicho procesador!

Desde mi propia experiencia, si tiene muchas E / S, múltiples hilos es bueno. Si tiene un trabajo muy intenso en memoria (leer fuente 1, leer fuente 2, cálculo rápido, escribir), entonces tener más hilos no ayuda. Nuevamente, esto depende de la cantidad de datos que lea / escriba simultáneamente (es decir, si usa SSE 4.2 y lee valores de 256 bits, eso detiene todos los hilos en su paso ... en otras palabras, 1 hilo es probablemente mucho más fácil de implementar y probablemente casi tan rápido si no es realmente más rápido. Esto dependerá de su arquitectura de proceso y memoria, algunos servidores avanzados administran rangos de memoria separados para núcleos separados, por lo que los hilos separados serán más rápidos suponiendo que sus datos se archiven correctamente ... por eso, en algunos arquitecturas, 4 procesos se ejecutarán más rápido que 1 proceso con 4 hilos).


44
Probablemente hay otros, pero el que conozco es el procesador POWER de IBM. Tenían sistemas con 4 u 8 hilos por procesadores. Ahora pueden poner más núcleos, por lo que ofrecen 2 hilos por núcleo en su lugar ...
Alexis Wilke

Esto es antiguo, pero la mayoría de Intel i5, i7 tiene CPU de varios subprocesos como, por ejemplo, las CPU i7 suelen tener 4 núcleos, pero 8 subprocesos.
Edgar. A

44
Los procesadores no tienen hilos. Tienen núcleos físicos y lógicos. Con hyperthreading, un solo núcleo físico funciona como dos núcleos lógicos. Tenía un técnico que insistía en que los procesadores que tenían hilos eran reales, así que dibujé una imagen en la pizarra de un procesador con un eje de hilo sobresaliendo.

@TechnikEmpire Eche un vistazo a este intel.com/content/www/us/en/processors/core/… , tal vez luego pueda contactar a intel y dibujar sus hilos también.
g7k

24

El rendimiento real dependerá de cuánto rendimiento voluntario hará cada hilo. Por ejemplo, si los subprocesos NO hacen E / S en absoluto y no utilizan servicios del sistema (es decir, están 100% enlazados a la CPU), entonces 1 subproceso por núcleo es lo óptimo. Si los hilos hacen algo que requiere esperar, entonces tendrá que experimentar para determinar el número óptimo de hilos. 4000 subprocesos incurrirían en una sobrecarga de programación significativa, por lo que probablemente tampoco sea óptimo.


21

La respuesta depende de la complejidad de los algoritmos utilizados en el programa. Se me ocurrió un método para calcular el número óptimo de subprocesos haciendo dos mediciones de los tiempos de procesamiento Tn y Tm para dos números arbitrarios de subprocesos 'n' y 'm'. Para algoritmos lineales, el número óptimo de hilos será N = sqrt ((m n (Tm * (n-1) - Tn * (m-1))) / (n Tn-m Tm)).

Lea mi artículo sobre los cálculos del número óptimo para varios algoritmos: pavelkazenin.wordpress.com


44
¿Por qué es rechazado? Lo siento, pero esta es la mejor respuesta a esta pregunta. gonzalo aborda la parte audaz de la pregunta, y pkazen aborda el título. Ambas respuestas son muy útiles, pero la respuesta pkazen es relevante porque tenemos un método sistemático para aproximar el número de hilos. Incluso da la fórmula para los algoritmos de línea.
tobiak777

1
No voté en contra, pero si lo hiciera sería sobre la base de que no hay una explicación real de por qué o cómo el número óptimo de hilos podría estar relacionado con la complejidad del algoritmo, excepto leyendo el artículo completo vinculado, que es una lectura larga (debido a la complejidad del artículo). Más allá de eso, algunos aspectos del artículo no están claros para mí, lo más importante es cómo los resultados experimentales confirman la teoría.
Codebling el

Además, creo que este cálculo supone que tienes un número infinito de núcleos de CPU. Si bien esta es definitivamente información valiosa, la pregunta se refiere a máquinas reales con un pequeño número de núcleos.
Navneeth

9

Pensé que agregaría otra perspectiva aquí. La respuesta depende de si la pregunta está asumiendo un escalado débil o un escalado fuerte.

De Wikipedia :

Escalado débil: cómo varía el tiempo de solución con el número de procesadores para un tamaño de problema fijo por procesador.

Escalado fuerte: cómo varía el tiempo de solución con la cantidad de procesadores para un tamaño de problema total fijo.

Si la pregunta asume escalas débiles, entonces la respuesta de @ Gonzalo es suficiente. Sin embargo, si la pregunta está asumiendo una gran escala, hay algo más que agregar. En una escala fuerte, está asumiendo un tamaño de carga de trabajo fijo, por lo que si aumenta el número de subprocesos, disminuye el tamaño de los datos en los que cada subproceso necesita trabajar. En las CPU modernas, los accesos a la memoria son caros y sería preferible mantener la localidad manteniendo los datos en cachés. Por lo tanto, la cantidad óptima probable de subprocesos se puede encontrar cuando el conjunto de datos de cada subproceso encaja en la memoria caché de cada núcleo (no voy a entrar en detalles para discutir si se trata de caché (s) L1 / L2 / L3 del sistema).

Esto es válido incluso cuando el número de hilos supera el número de núcleos. Por ejemplo, suponga que hay 8 unidades arbitrarias (o AU) de trabajo en el programa que se ejecutarán en una máquina de 4 núcleos.

Caso 1: ejecutar con cuatro subprocesos donde cada subproceso necesita completar 2 UA. Cada subproceso tarda 10 segundos en completarse ( con muchos errores de caché ). Con cuatro núcleos, la cantidad total de tiempo será de 10 segundos (10 segundos * 4 hilos / 4 núcleos).

Caso 2: ejecutar con ocho subprocesos donde cada subproceso necesita completar 1 UA. Cada subproceso toma solo 2 segundos (en lugar de 5 segundos debido a la cantidad reducida de errores de caché ). Con cuatro núcleos, el tiempo total será de 4 segundos (2 segundos * 8 hilos / 4 núcleos).

Simplifiqué el problema e ignoré los gastos generales mencionados en otras respuestas (p. Ej., Cambios de contexto), pero espero que entiendas que podría ser beneficioso tener más cantidad de hilos que la cantidad de núcleos disponibles, dependiendo del tamaño de datos que ' está tratando con


7

4000 hilos a la vez es bastante alto.

La respuesta es sí y no. Si está bloqueando mucho las E / S en cada subproceso, entonces sí, podría mostrar aceleraciones significativas haciendo probablemente hasta 3 o 4 subprocesos por núcleo lógico.

Sin embargo, si no está bloqueando muchas cosas, la sobrecarga adicional con el enhebrado lo hará más lento. Por lo tanto, use un perfilador y vea dónde están los cuellos de botella en cada pieza posiblemente paralela. Si está haciendo cálculos pesados, más de 1 hilo por CPU no ayudará. Si está transfiriendo mucha memoria, tampoco será de ayuda. Sin embargo, si está haciendo muchas E / S, como acceso a disco o acceso a Internet, sí, varios subprocesos ayudarán hasta cierto punto, o al menos harán que la aplicación sea más receptiva.


7

Punto de referencia.

Comenzaría a aumentar el número de subprocesos para una aplicación, comenzando en 1, y luego iría a algo así como 100, ejecutaría tres y cinco pruebas para cada número de subprocesos, y construiría un gráfico de la velocidad de operación frente al número de subprocesos .

Debería que la caja de cuatro hilos sea óptima, con ligeros aumentos en el tiempo de ejecución después de eso, pero tal vez no. Puede ser que su aplicación tenga un ancho de banda limitado, es decir, el conjunto de datos que está cargando en la memoria es enorme, está obteniendo muchos errores de caché, etc., de modo que 2 hilos son óptimos.

No puedes saber hasta que pruebes.


3

Encontrará cuántos subprocesos puede ejecutar en su máquina ejecutando el comando htop o ps que devuelve el número de procesos en su máquina.

Puede usar la página de manual sobre el comando 'ps'.

man ps

Si desea calcular el número de procesos de todos los usuarios, puede usar uno de estos comandos:

  1. ps -aux| wc -l
  2. ps -eLf | wc -l

Número de cálculo de un proceso de usuario:

  1. ps --User root | wc -l

Además, puede usar "htop" [Referencia] :

Instalación en Ubuntu o Debian:

sudo apt-get install htop

Instalación en Redhat o CentOS:

yum install htop
dnf install htop      [On Fedora 22+ releases]

Si desea compilar htop desde el código fuente, lo encontrará aquí .


2

Lo ideal es 1 hilo por núcleo, siempre que ninguno de los hilos se bloquee.

Un caso en el que esto puede no ser cierto: hay otros subprocesos ejecutándose en el núcleo, en cuyo caso más subprocesos pueden darle a su programa una porción mayor del tiempo de ejecución.


Depende de si desea que los procesos en segundo plano de los usuarios se ejecuten como basura mientras su aplicación se ejecuta en ese momento. Para el caso, puede establecer una prioridad en tiempo real para cada hilo y obtener la máxima cantidad de energía. Pero a los usuarios les gusta la multitarea.
Earlz el

2
Bueno, estamos tratando con una aplicación mágica idealmente paralelizable. Si alguna vez crease algo así, me sentiría con derecho a acaparar la CPU tanto como quiera.
patros

2

Un ejemplo de muchos subprocesos ("grupo de subprocesos") frente a uno por núcleo es el de implementar un servidor web en Linux o en Windows.

Dado que los sockets se sondean en Linux, muchos subprocesos pueden aumentar la probabilidad de que uno de ellos realice el sondeo del socket correcto en el momento adecuado, pero el costo total de procesamiento será muy alto.

En Windows, el servidor se implementará utilizando los puertos de finalización de E / S (IOCP), lo que hará que el evento de la aplicación sea controlado: si una E / S completa el sistema operativo, se inicia un subproceso en espera para procesarlo. Cuando se completa el procesamiento (generalmente con otra operación de E / S como en un par de solicitud-respuesta), el subproceso regresa al puerto IOCP (cola) para esperar la próxima finalización.

Si no se ha completado ninguna E / S, no hay que procesar nada y no se inicia ningún subproceso.

De hecho, Microsoft recomienda no más de un hilo por núcleo en las implementaciones de IOCP. Cualquier E / S puede estar conectada al mecanismo IOCP. Los COI también pueden ser publicados por la aplicación, si es necesario.


No sé de qué Linux estás hablando, pero mis bloqueos hasta que llega una conexión. Le sugiero que lea algunas cosas sobre select () y FD_SET () y funciones / macros similares.
Alexis Wilke

Ok, entonces ¿no hay una forma asincrónica que regrese de inmediato?
Olof Forshell

Desde la página de manual select ():timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
Alexis Wilke

0

hablando desde el punto de vista de la computación y la memoria (computación científica) 4000 hilos hará que la aplicación se ejecute muy lentamente. Parte del problema es una sobrecarga muy alta de cambio de contexto y muy probablemente una localidad de memoria muy pobre.

Pero también depende de tu arquitectura. Desde donde escuché, se supone que los procesadores Niagara pueden manejar múltiples subprocesos en un solo núcleo utilizando algún tipo de técnica avanzada de canalización. Sin embargo, no tengo experiencia con esos procesadores.


0

Espero que esto tenga sentido, verifique la utilización de la CPU y la memoria y ponga un valor umbral. Si se cruza el valor umbral, no permita crear un nuevo hilo, de lo contrario permita ...

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.