¿Cómo programar la asignación de hilos en procesadores multinúcleo?

13

Me gustaría experimentar con subprocesos en un procesador multinúcleo, por ejemplo, para crear un programa que use dos subprocesos diferentes ejecutados por dos núcleos de procesador diferentes.

Sin embargo, no me queda claro en qué nivel se asignan los hilos a los diferentes núcleos. Puedo imaginar los siguientes escenarios (dependiendo del sistema operativo y la implementación del lenguaje de programación):

  1. La asignación de hilos es administrada por el sistema operativo. Los subprocesos se crean mediante llamadas al sistema operativo y, si el proceso se ejecuta en un procesador de varios núcleos, el sistema operativo automáticamente intenta asignar / programar diferentes subprocesos en diferentes núcleos.
  2. La asignación de hilos es administrada por la implementación del lenguaje de programación. La asignación de hilos a diferentes núcleos requiere llamadas especiales del sistema, pero las bibliotecas de hilos estándar del lenguaje de programación manejan esto automáticamente cuando uso la implementación de hilos estándar para ese lenguaje.
  3. La asignación de hilos debe programarse explícitamente. En mi programa, tengo que escribir código explícito para detectar cuántos núcleos están disponibles y asignar diferentes subprocesos a diferentes núcleos utilizando, por ejemplo, funciones de biblioteca.

Para hacer la pregunta más específica, imagine que he escrito mi aplicación multiproceso en Java o C ++ en Windows o Linux. ¿Mi aplicación verá y usará mágicamente múltiples núcleos cuando se ejecute en un procesador multinúcleo (porque todo es administrado por el sistema operativo o por la biblioteca de hilos estándar), o tengo que modificar mi código para conocer los múltiples núcleos? ?

Giorgio
fuente

Respuestas:

11

¿Mi aplicación verá y usará mágicamente múltiples núcleos cuando se ejecute en un procesador multinúcleo (porque todo es administrado por el sistema operativo o por la biblioteca de hilos estándar), o tengo que modificar mi código para conocer los múltiples núcleos? ?

Respuesta simple: Sí, generalmente será administrado por el sistema operativo o la biblioteca de subprocesos.

El subsistema de subprocesos en el sistema operativo asignará subprocesos a los procesadores de forma prioritaria (su opción 1). En otras palabras, cuando un subproceso ha terminado de ejecutarse para su asignación de tiempo o bloques, el planificador busca el siguiente subproceso de mayor prioridad y lo asigna a la CPU. Los detalles varían de un sistema operativo a otro.

Dicho esto, existen las opciones 2 (administradas por lenguaje de programación) y 3 (explícitamente). Por ejemplo, la biblioteca de tareas y async / await en versiones recientes de .Net le dan al desarrollador una forma mucho más fácil de escribir código paralelo (es decir, que puede ejecutarse simultáneamente). Los lenguajes de programación funcional son paralelizables de forma innata y algunos tiempos de ejecución ejecutarán diferentes partes del programa en paralelo si es posible.

En cuanto a la opción 3 (explícitamente), Windows le permite configurar la afinidad de subprocesos (especificando en qué procesadores se puede ejecutar un subproceso). Sin embargo, esto generalmente no es necesario en todos los sistemas críticos, excepto el más rápido y el tiempo de respuesta. La asignación efectiva de hilo a procesador depende en gran medida del hardware y es muy sensible a otras aplicaciones que se ejecutan simultáneamente.

Si desea experimentar, cree una tarea intensiva de CPU de larga ejecución, como generar una lista de números primos o crear un conjunto de Mandelbrot. Ahora cree dos hilos en su biblioteca favorita y ejecute ambos hilos en una máquina multiprocesador (en otras palabras, casi cualquier cosa lanzada en los últimos años). Ambas tareas deben completarse aproximadamente al mismo tiempo porque se ejecutan en paralelo.

akton
fuente
Gracias por la explicación (+1). Mi programa de prueba es una implementación de tipo de fusión. En la fase dividida, quiero crear diferentes subprocesos siempre que haya núcleos disponibles. Por ejemplo, con dos núcleos, cada mitad de una matriz se ordenaría por un hilo / núcleo diferente. Durante la fusión, los hilos superfluos se unirían / ​​terminarían.
Giorgio el
La clasificación es difícil de paralelizar de esta manera si los datos se distribuyen aleatoriamente. Sí, puede dividirlo y luego ordenar cada porción en un hilo diferente, pero de todos modos tendrá que fusionar todas las porciones. Si los hilos comparten estructuras de datos, también puede tener problemas de contención o bloqueo. No digo que la ordenación no pueda beneficiarse de los subprocesos, pero no será una mejora lineal del rendimiento.
akton el
Las dos mitades de una matriz se pueden ordenar de forma independiente porque no se comparten datos. Solo la primera división y la última combinación deberán realizarse mediante un subproceso que manipule toda la matriz o lista que contiene los datos. Esto significa que una exploración completa de los datos no se puede ejecutar en paralelo; todos los escaneos restantes pueden.
Giorgio el
Por supuesto, también considero sus ejemplos como buenos candidatos. Estoy más familiarizado con el tipo de fusión en este momento (y he implementado una versión no paralela del mismo), lo que (tal vez) haría que el tipo de fusión sea más adecuado para mí como primer intento.
Giorgio el
2
Añadiría a esta respuesta que los buenos sistemas operativos son lo suficientemente inteligentes como para equilibrar el costo de asignarle a una tarea un intervalo de tiempo en una CPU o núcleo diferente con el de la inanición a corto plazo. En las arquitecturas donde importa, el resultado tiende a parecerse a la afinidad automática. El sistema operativo se ha creado para que todos los trabajos se ejecuten lo más rápido posible, y es posible que se esté disparando en el pie atando hilos a los núcleos y obstaculizando su capacidad para tomar esas decisiones.
Blrfl
-1

Una vez tuve un gran entorno SGI IRIX. Solo por el gusto de hacerlo, escribí un pequeño programa Java multiproceso (que no hizo más que consumir ciclos de CPU) y creé 12 hilos en él. El trabajo abarcó 12 CPU en la arquitectura NUMA. Tal vez buscaré el programa y lo ejecutaré en los Dell R910s y comprobaré ...

P. Prabhakar
fuente
3
Esta respuesta realmente no agrega mucho a la respuesta existente. Quizás si usted explica por qué la JVM en el sistema SGI asignó hilos al núcleo ...
Jay Elston