.net - Uso de múltiples núcleos, subprocesos, grupos de subprocesos
multithreading multicore (2)
Además de la excelente y completa respuesta de jalf, tenga en cuenta que "Parallel Extensions" (que debe incluirse en .NET 4.0) tiene una gran cantidad de código dedicado a asignar trabajo (de colas) a núcleos de manera uniforme, incluido el robo de trabajo y potencialmente pepitas como cuidar qué núcleo está "más cerca" de la memoria en la que reside el trabajo.
Entonces, con .NET 4.0, usando cosas como Parallel.For
, etc., debería obtener mucho de esto gratis. Y, en general, el sistema operativo es lo suficientemente inteligente como para que funcione desde la perspectiva del forastero. jalf ha dado muchos detalles acerca de lo que ocurre bajo el capó, pero la mayoría de las veces no necesita este nivel de detalle, a menos que esté solucionando algunos problemas de rendimiento con código altamente enhebrado.
Tengo algunas preguntas sobre la programación multiproceso y el uso de varios núcleos.
En particular, me pregunto cómo el sistema operativo y / o el marco (esto es .NET) trata con núcleos que se usan mucho.
Aquí están mis preguntas con respecto a los hilos:
- Cuando se genera un nuevo hilo, ¿cuál es el algoritmo para asignar el hilo a un núcleo particular?
- Tipo de algoritmo Round-robin
- Aleatorio
- El núcleo actualmente menos utilizado
- Si no fuera el núcleo actualmente menos utilizado, ¿este tipo de código determinaría a este enano el uso típico de un hilo y así empeoraría las cosas?
- ¿Los hilos se mueven de un núcleo a otro durante su vida útil? Si es así, ¿se trata de manejar núcleos que por alguna razón se "usan en exceso" y, por lo tanto, el sistema operativo intenta mezclar los hilos con núcleos menos utilizados para ayudar al sistema? Si no, de nuevo, ¿por qué no?
Mi última pregunta, que es básicamente una reutilización de lo anterior, es sobre la clase .NET ThreadPool, que maneja cosas como .BeginInvoke y cosas por el estilo. ¿Esta clase hace algo de esto? Si no, ¿por qué no, o debería?
¿Hay alguna manera de modificar este manejo, una especie de sugerencia en el sistema operativo que este hilo en particular, por favor, preste más atención cuando se le asigna un núcleo, ya que sé que usará una gran cantidad de CPU. ¿Eso tendría sentido? ¿O sería "una gran cantidad de CPU" solo relativo y, por lo tanto, no lo suficientemente bueno?
Cuando se genera un nuevo hilo, ¿cuál es el algoritmo para asignar el hilo a un núcleo particular?
Eso depende completamente del sistema operativo. Y la respuesta suele ser un esquema round-robin muy modificado. Cada x milisegundos, se interrumpe un núcleo y se coloca un nuevo hilo (para que no haya un "núcleo menos utilizado". Siempre que haya hilos listos para ejecutarse, cada núcleo tendrá algo que hacer).
En Windows, creo que el hilo / proceso con la prioridad más alta siempre se selecciona para su ejecución. (Por lo tanto, si tiene un proceso ejecutándose con alta prioridad en un sistema de núcleo único, ese proceso se ejecutará potencialmente el 100% del tiempo, privando a todos los demás procesos. Por supuesto, esto solo se aplica si ese proceso nunca se bloquea, lo que es poco probable el mundo real.
Y, por supuesto, debido a que un sistema operativo moderno como Windows es complejo, hay mucho más. Ciertos procesos reciben un tratamiento preferencial de vez en cuando, pero como regla general, Windows siempre seleccionará procesos de alta prioridad (por lo que podrías congelar tu computadora devolviendo la prioridad de "tiempo real" del proceso en los días de singlecore). )
En Linux, los procesos de menor prioridad también se programan regularmente, pero no con la misma frecuencia.
Pero lo mejor que puede hacer es asumir que el sistema operativo será un esquema justo, y luego tratar de jugar bien con el resto del sistema. (Cede / bloquea / duerme cuando no tienes nada que hacer, permitiendo que se ejecuten otros subprocesos).
¿Los hilos se mueven de un núcleo a otro durante su vida útil?
Por supuesto. Imagine que tiene tres hilos ejecutándose en un sistema dualcore. Muéstrame un calendario justo que no implique mover hilos regularmente entre núcleos.
Mi última pregunta, que es básicamente una reutilización de lo anterior, es sobre la clase .NET ThreadPool, que maneja cosas como .BeginInvoke y cosas por el estilo. ¿Esta clase hace algo de esto? Si no, ¿por qué no, o debería? ¿Qué cosas? Enrutar la programación y elegir núcleos para ejecutar? No, el threadpool es simplemente un mecanismo para reutilizar hilos para tareas múltiples, en lugar de tener que crear un hilo nuevo para cada tarea y luego cerrarlo después.
¿Hay alguna manera de modificar este manejo, tipo de sugerencia en el sistema operativo que este hilo en particular?
Para eso es la prioridad del hilo / proceso. Si tiene un hilo que debe obtener mucho tiempo de CPU, incluso cuando hay otros subprocesos intensivos en CPU en ejecución, aumente la prioridad del hilo. Pero maneja con cuidado. Por lo general, no hay muchos subprocesos intensivos en CPU en ejecución, lo que significa que incluso con una prioridad normal, obtendrá el 99.9% del tiempo de CPU. Como dije, Windows planifica los hilos de mayor prioridad de manera muy agresiva, por lo que solo aumenta la prioridad si realmente lo dices en serio .