Número óptimo de hilos por núcleo

Digamos que tengo una CPU de 4 núcleos y deseo ejecutar algunos procesos en la cantidad de tiempo mínima. El proceso es idealmente paralelizable, por lo que puedo ejecutar trozos de él en un número infinito de hilos y cada hilo toma la misma cantidad de tiempo.

Como tengo 4 núcleos, no espero ninguna aceleración al ejecutar más hilos que núcleos, ya que un solo núcleo solo es capaz de ejecutar un solo hilo 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 paralelizable en más hilos que núcleos? En otras palabras, ¿finalizará mi proceso más rápido, más lento o en la misma cantidad de tiempo si lo ejecuto utilizando 4000 hilos en lugar de 4 hilos?

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

No hace mucho, estaba haciendo pruebas de rendimiento en una máquina de 2 núcleos cuádruples que ejecutaba una aplicación ASP.NET en Mono con una carga bastante aceptable. 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 particular, el mejor rendimiento estaba entre 36 y 40 subprocesos. Cualquier cosa fuera de esos límites funcionaba peor. ¿Lección aprendida? Si yo fuera usted, lo probaría con diferentes números de hilos hasta que encuentre el número correcto para su aplicación.

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

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

enter image description here

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

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

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

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

Hay dos cosas que se deben tener en cuenta ahora: la cantidad de núcleos y la cantidad de subprocesos que se pueden ejecutar dentro de cada núcleo.

Con los procesadores Intel, la cantidad de subprocesos está definida por Hyperthreading, que es solo 2 (cuando esté disponible). Pero Hyperthreading reduce el tiempo de ejecución en dos, ¡incluso cuando no usa 2 hilos! (es decir, 1 canal compartido entre dos procesos: esto es bueno cuando tienes 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 en ejecución paralela 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 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 tienes muchas E / S, múltiples hilos son buenos. Si tiene un trabajo intensivo en memoria (lectura de fuente 1, fuente de lectura 2, cálculo rápido, escritura), tener más hilos no ayuda. De nuevo, esto depende de la cantidad de datos que lea / escriba simultáneamente (es decir, si utiliza 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 sea más rápido o incluso más rápido. Esto dependerá de la architecture de tu proceso y memoria, algunos servidores avanzados administran rangos de memoria separados para núcleos separados, por lo que los subprocesos serán más rápidos si asumimos que tus datos están archivados correctamente … por eso, en algunos architectures, 4 procesos se ejecutarán más rápido que 1 proceso con 4 hilos).

El rendimiento real dependerá de la cantidad de rendimiento voluntario que cada hilo hará. Por ejemplo, si los subprocesos no hacen NINGUNA E / S en absoluto y no utilizan ningún servicio del sistema (es decir, están 100% vinculados a la CPU), entonces 1 subproceso por núcleo es el óptimo. Si los subprocesos hacen algo que requiera esperar, deberá experimentar para determinar la cantidad óptima de subprocesos. 4000 hilos incurrirían en una sobrecarga de progtwigción significativa, por lo que probablemente tampoco sea óptimo.

La respuesta depende de la complejidad de los algoritmos utilizados en el progtwig. Se me ocurrió un método para calcular el número óptimo de hilos haciendo dos medidas de tiempos de procesamiento Tn y Tm para dos números arbitrarios de hilos ‘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)).

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

Pensé que agregaría otra perspectiva aquí. La respuesta depende de si la pregunta está asumiendo escalas débiles o escalas fuertes.

De la Wikipedia :

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

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

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

Esto es válido incluso cuando la cantidad de hilos excede la cantidad de núcleos. Por ejemplo, supongamos que hay 8 unidades arbitrarias (o AU) de trabajo en el progtwig que se ejecutarán en una máquina de 4 núcleos.

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

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

Simplifiqué el problema e ignoré los gastos generales mencionados en otras respuestas (por ejemplo, los cambios de contexto) pero espero que entienda que podría ser beneficioso tener más hilos que la cantidad de núcleos disponibles, dependiendo del tamaño de los datos que utilice. estoy tratando con

4000 hilos a la vez es bastante alto.

La respuesta es sí y no. Si está realizando muchas lockings de E / S en cada hilo, entonces sí, podría mostrar aceleraciones significativas hasta probablemente 3 o 4 hilos por núcleo lógico.

Sin embargo, si no estás bloqueando muchas cosas, la sobrecarga adicional con el enhebrado lo hará más lento. Así que use un generador de perfiles y vea dónde están los cuellos de botella en cada posible pieza paralela. Si está haciendo cálculos pesados, entonces más de 1 hilo por CPU no ayudará. Si está haciendo una gran cantidad de transferencia de memoria, tampoco ayudará. Si está realizando muchas operaciones de E / S, como acceso a disco o acceso a Internet, sí, varios hilos ayudarán hasta cierto punto o, al menos, harán que la aplicación sea más receptiva.

Punto de referencia.

Comenzaría a boost el número de subprocesos para una aplicación, comenzando en 1, y luego ir a algo así como 100, ejecutar tres y cinco bashs para cada número de subprocesos, y crear un gráfico de velocidad de operación vs. número de subprocesos .

Debería saber que la caja de cuatro hilos es óptima, con leves 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á recibiendo muchos errores de caché, etc., de modo que 2 subprocesos son óptimos.

No puedes saber hasta que pruebes.

Encontrará la cantidad de hilos que 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 man 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

Cálculo del número de un proceso de usuario:

  1. ps --User root | wc -l

Además, puede usar “htop” [Referencia] :

Instalando 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 comstackr htop desde el código fuente, lo encontrará aquí .

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

Como los sockets se sondean en Linux, muchos hilos pueden boost la probabilidad de que uno de ellos interrogue al socket correcto en el momento correcto, pero el costo general de procesamiento será muy alto.

En Windows, el servidor se implementará utilizando Puertos de finalización de E / S (IOCP), lo que hará que la aplicación sea impulsada por eventos: si se completa una E / S, el OS inicia una secuencia de espera para procesarla. Cuando se ha completado el procesamiento (generalmente con otra operación de E / S como en un par de solicitud-respuesta), el hilo vuelve al puerto IOCP (cola) para esperar la siguiente finalización.

Si no se ha completado ninguna E / S, no se debe procesar 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 se puede unir al mecanismo de IOCP. Los IOC también pueden ser publicados por la aplicación, si es necesario.

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 que se ejecutan en el núcleo, en cuyo caso más subprocesos pueden darle a su progtwig una porción más grande del tiempo de ejecución.

hablando desde el punto de vista de computación y memoria (informática científica) 4000 hilos harán que la ejecución de la aplicación sea realmente lenta. 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 architecture. Desde donde oí, se supone que los procesadores Niagara son capaces de manejar múltiples hilos en un solo núcleo usando algún tipo de técnica de canalización avanzada. Sin embargo, no tengo experiencia con esos procesadores.

Espero que esto tenga sentido, compruebe la utilización de la CPU y la memoria y ponga algún valor de umbral. Si se cruza el valor del umbral, no permita la creación de un nuevo hilo, sino permita …