Estoy cansado de escuchar que la gente recomienda que use solo un subproceso por procesador, ¡mientras que muchos programas usan hasta 100 por proceso! tomar por ejemplo algunos programas comunes
vb.net ide uses about 25 thread when not debugging
System uses about 100
chrome uses about 19
Avira uses more than about 50
Cada vez que publico una pregunta relacionada con subprocesos, casi siempre me recuerdan que no debería usar más de un subproceso por procesador, y todos los programas que menciono anteriormente están arruinando mi sistema con un solo procesador.
Respuestas:
Posiblemente en HPC, donde desea la máxima eficiencia, pero por lo demás, ¡la cosa más estúpida que he escuchado hoy!
Debe usar la cantidad de subprocesos que sean apropiados para el diseño del programa y que aún así ofrezcan un rendimiento aceptable.
Para un servidor web, podría ser razonable disparar un hilo para cada conexión entrante (aunque hay mejores formas para servidores muy cargados).
Para un ide cada herramienta que se ejecuta en su propio hilo no es irrazonable. Sospecho que muchos de los hilos informados para .Net IDE son cosas como el inicio de sesión y las tareas de E / S que se inician en sus propios hilos para que puedan continuar desbloqueados.
fuente
El consejo de un hilo por núcleo se aplica cuando el propósito es la velocidad a través de la ejecución paralela.
Una razón completamente diferente e igualmente válida es la simplicidad del código cuando tiene que responder a eventos impredecibles. Entonces, si un programa tiene que escuchar en 100 zócalos y parece prestar toda su atención a cada uno, es un uso perfecto para el enhebrado. Otro ejemplo es una interfaz de usuario, donde un hilo maneja los eventos de la interfaz de usuario, mientras que otro procesa en segundo plano.
fuente
Desea un subproceso para cada cálculo que puede proceder a velocidades diferentes que otros cálculos.
Para el cómputo paralelo de CPU, que viene en grandes bloques de trabajo, generalmente desea un subproceso por CPU, porque una vez que están ocupados, más subprocesos no ayudan y solo crean una sobrecarga del planificador. Si los bloques de trabajo tienen tamaños irregulares en el tiempo, o se generan dinámicamente en tiempo de ejecución (a menudo ocurre cuando tiene grandes estructuras de datos complejas para procesar), es posible que desee adjuntar esos bloques a muchos subprocesos, por lo que un planificador siempre tiene un gran configurado para elegir cuándo se completa algún bloque de trabajo, para mantener ocupadas todas las CPU.
Para el cálculo vinculado de E / S, generalmente desea un subproceso para cada "canal" de E / S independiente, ya que se comunican a diferentes velocidades, y los subprocesos bloqueados en el canal no impiden que otros subprocesos avancen.
fuente
La regla general para los subprocesos es que desea al menos un subproceso de trabajo "activo" (capaz de ejecutar sus comandos inmediatamente dado el tiempo de CPU) para cada "unidad de ejecución" disponible en la computadora. Una "unidad de ejecución" es un procesador de instrucciones lógicas, por lo que un servidor hiperprocesado Xeon de cuatro núcleos y cuatro núcleos tendría 32 UE (4 chips, 4 núcleos por chip, cada uno hipertreprocesado). Su Core i7 promedio tendría 8.
Un subproceso por UE es el uso más completo de la potencia de la CPU, siempre que los subprocesos siempre estén en funcionamiento; este casi nunca es el caso, ya que los subprocesos necesitan acceso a la memoria no almacenada en caché, el disco duro, los puertos de red, etc. que deben esperar y que no requieren atención activa de la CPU para funcionar. Por lo tanto, puede aumentar aún más la eficiencia general con más hilos en cola y con muchas ganas de ir. Esto tiene un costo; cuando una CPU cambia un subproceso, debe almacenar en caché los registros del subproceso, el puntero de ejecución y otra información de estado que normalmente se mantiene en el funcionamiento más interno de una UE y se accede muy rápidamente, permitiendo que otras UE en ese chip de la CPU lo recojan. También requiere hilos en el sistema operativo para decidir a qué hilo se debe cambiar. Por último, cuando una UE cambia hilos, pierde las ganancias de rendimiento de la canalización que utilizan la mayoría de las arquitecturas de procesador; Tiene que lavar la tubería antes de cambiar los hilos. Pero, como todo esto todavía lleva mucho menos tiempo en promedio que simplemente esperar que el disco duro o incluso la RAM vuelvan con información, vale la pena el costo.
Sin embargo, en general, una vez que se supera el doble del número de subprocesos "activos" que los de la UE, el sistema operativo comienza a gastar más de los subprocesos de programación de tiempo de la UE, y las UE pasan más tiempo intercambiando entre ellos, de lo que se gastan en la ejecución de subprocesos activos de programas. Este es el punto de las deseconomías de escala; en realidad, llevará más tiempo ejecutar un algoritmo multiproceso si agregara un subproceso adicional en este punto.
Por lo tanto, en general, desea mantener al menos tantos subprocesos en su programa como UE en la computadora, pero desea evitar tener más del doble de ese número que no está esperando o durmiendo.
fuente
Debe usar un hilo para:
Cada procesador que necesita para mantenerse ocupado.
Cada E / S puede ser útil al mismo tiempo que no se puede realizar sin bloqueo. (Por ejemplo, lee desde un disco local).
Cada tarea que requiere un subproceso dedicado, por ejemplo, llamar a una biblioteca que no tiene una interfaz sin bloqueo o donde las interfaces sin bloqueo no son apropiadas. Esto incluye tareas como monitorear el reloj del sistema, disparar temporizadores, etc.
Unos pocos adicionales para proteger contra bloqueos inesperados, como fallas de página.
Unos pocos más para proteger contra el bloqueo esperado que no vale la pena optimizar, por ejemplo, en código no crítico. (Por ejemplo, si rara vez necesita hacer una solicitud de DNS, probablemente no valga la pena hacer las solicitudes de DNS de forma asincrónica. Simplemente cree algunos hilos adicionales y le facilitará la vida).
Si sigue la regla de "un subproceso por procesador", entonces todo su código es crítico para el rendimiento. Cualquier código que se bloquee por alguna razón significa que su proceso no puede usar ese procesador. Eso hace que la programación sea mucho más difícil sin una buena razón.
fuente
Puede generar procesos y subprocesos para permitir la utilización de un sistema multinúcleo \ multiprocesador para un solo programa, en cuyo caso no obtendrá ningún beneficio (al menos para el único programa) de tener más subprocesos \ procesos y núcleos.
O puede tener rutinas que sondeen un evento que normalmente bloquea la ejecución posterior. En lugar de atar la CPU con sondeo, en su lugar puede crear un hilo que se quedará en un estado inactivo hasta que el evento apropiado lo despierte. Este método se usa muy comúnmente en servidores web y colas de eventos de GUI. La mayoría de los programas quieren tener algún tipo de almacén de datos central (incluso si es el código de ejecución del programa) al que pueden acceder todos los subprocesos, así que supongo que es por eso que usan subprocesos en los procesos.
fuente
Las aplicaciones que menciona rara vez ejecutan todas esas decenas de hilos simultáneamente. La mayoría de ellos simplemente se sientan allí porque están en un grupo de hilos . La aplicación envía varias tareas a una cola, que se purga mediante subprocesos en el grupo de subprocesos.
¿Por qué el tamaño de la piscina es tan grande entonces? Porque, a menudo, los subprocesos tienen que esperar otros recursos como el disco, la red, el usuario, algún otro subproceso, etc. Mientras un subproceso está esperando, es apropiado ejecutar otros subprocesos para utilizar completamente el procesador. Sin embargo, dimensionar la piscina de manera adecuada es complicado. Muy pocos subprocesos y perderá rendimiento porque el procesador no se utiliza por completo mientras espera algo. Demasiados subprocesos y perderá rendimiento debido al cambio entre ellos.
fuente