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?
fuente
Estoy de acuerdo con la respuesta de @ Gonzalo. Tengo un proceso que no hace E / S, y esto es lo que he encontrado:
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.
fuente
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).
fuente
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.
fuente
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
fuente
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
fuente
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.
fuente
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.
fuente
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'.
Si desea calcular el número de procesos de todos los usuarios, puede usar uno de estos comandos:
ps -aux| wc -l
ps -eLf | wc -l
Número de cálculo de un proceso de usuario:
ps --User root | wc -l
Además, puede usar "htop" [Referencia] :
Instalación en Ubuntu o Debian:
Instalación en Redhat o CentOS:
Si desea compilar htop desde el código fuente, lo encontrará aquí .
fuente
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.
fuente
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.
fuente
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.
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.
fuente
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 ...
fuente