En arquitectura informática , el multihilo es la capacidad de una unidad central de procesamiento (CPU) (o un solo núcleo en un procesador multinúcleo ) de proporcionar múltiples subprocesos de ejecución .
El paradigma de subprocesamiento múltiple se ha vuelto más popular a medida que los esfuerzos por explotar aún más el paralelismo a nivel de instrucción se estancaron desde fines de la década de 1990. Esto permitió que el concepto de computación de alto rendimiento resurgiera del campo más especializado del procesamiento de transacciones . Si bien es muy difícil acelerar aún más un solo subproceso o un solo programa, la mayoría de los sistemas informáticos en realidad realizan múltiples tareas entre varios subprocesos o programas. Por lo tanto, las técnicas que mejoran el rendimiento de todas las tareas dan como resultado ganancias generales en el rendimiento.
Las dos técnicas principales para la computación de alto rendimiento son el multiprocesamiento y el multihilo .
Si un subproceso tiene muchos errores de caché , los demás subprocesos pueden seguir aprovechando los recursos informáticos no utilizados, lo que puede conducir a una ejecución general más rápida, ya que estos recursos habrían estado inactivos si solo se hubiera ejecutado un único subproceso. Además, si un subproceso no puede utilizar todos los recursos informáticos de la CPU (porque las instrucciones dependen de los resultados de las demás), ejecutar otro subproceso puede evitar que esos recursos queden inactivos.
Varios subprocesos pueden interferir entre sí cuando comparten recursos de hardware, como cachés o buffers de traducción (TLB). Como resultado, los tiempos de ejecución de un solo subproceso no mejoran y pueden degradarse, incluso cuando solo se ejecuta un subproceso, debido a frecuencias más bajas o etapas de canalización adicionales que son necesarias para acomodar el hardware de conmutación de subprocesos.
La eficiencia general varía; Intel afirma que su tecnología Hyper-Threading mejora hasta un 30% [1], mientras que un programa sintético que simplemente realiza un bucle de operaciones de punto flotante dependientes no optimizadas en realidad obtiene una mejora de velocidad del 100% cuando se ejecuta en paralelo. Por otro lado, los programas en lenguaje ensamblador ajustados manualmente que utilizan extensiones MMX o AltiVec y realizan prefetches de datos (como lo haría un buen codificador de video) no sufren fallas de caché o recursos informáticos inactivos. Por lo tanto, dichos programas no se benefician del subprocesamiento múltiple de hardware y, de hecho, pueden ver un rendimiento degradado debido a la contención por los recursos compartidos.
Desde el punto de vista del software, el soporte de hardware para el multiprocesamiento es más visible para el software, lo que requiere más cambios tanto en los programas de aplicación como en los sistemas operativos que el multiprocesamiento. Las técnicas de hardware utilizadas para soportar el multiprocesamiento a menudo son paralelas a las técnicas de software utilizadas para la multitarea de la computadora . La programación de subprocesos también es un problema importante en el multiprocesamiento.
El tipo más simple de multiprocesamiento ocurre cuando un subproceso se ejecuta hasta que se ve bloqueado por un evento que normalmente crearía un bloqueo de larga latencia. Este bloqueo puede ser un error de caché que tiene que acceder a la memoria externa del chip, lo que puede requerir cientos de ciclos de CPU para que los datos regresen. En lugar de esperar a que se resuelva el bloqueo, un procesador con subprocesos cambiaría la ejecución a otro subproceso que estuviera listo para ejecutarse. Solo cuando hubieran llegado los datos del subproceso anterior, este se volvería a colocar en la lista de subprocesos listos para ejecutarse .
Por ejemplo:
Conceptualmente, es similar a la multitarea cooperativa utilizada en los sistemas operativos en tiempo real , en la que las tareas renuncian voluntariamente al tiempo de ejecución cuando necesitan esperar algún tipo de evento. Este tipo de multiprocesamiento se conoce como multiprocesamiento en bloque, cooperativo o de grano grueso.
El objetivo de la compatibilidad con hardware de subprocesos múltiples es permitir un cambio rápido entre un subproceso bloqueado y otro subproceso listo para ejecutarse. Cambiar de un subproceso a otro significa que el hardware cambia de usar un conjunto de registros a otro. Para lograr este objetivo, se replica el hardware de los registros visibles del programa, así como algunos registros de control del procesador (como el contador del programa). Por ejemplo, para cambiar rápidamente entre dos subprocesos, el procesador se construye con dos conjuntos de registros.
El soporte de hardware adicional para subprocesos múltiples permite que el cambio de subprocesos se realice en un ciclo de CPU, lo que genera mejoras de rendimiento. Además, el hardware adicional permite que cada subproceso se comporte como si se estuviera ejecutando solo y no compartiera ningún recurso de hardware con otros subprocesos, lo que minimiza la cantidad de cambios de software necesarios dentro de la aplicación y el sistema operativo para admitir subprocesos múltiples.
Muchas familias de microcontroladores y procesadores integrados tienen múltiples bancos de registros para permitir un cambio rápido de contexto para las interrupciones. Estos esquemas pueden considerarse un tipo de subprocesamiento múltiple de bloques entre el subproceso del programa de usuario y los subprocesos de interrupción. [ cita requerida ]
El propósito del multithreading de grano fino es eliminar todos los bloqueos de dependencia de datos del pipeline de ejecución . Dado que un subproceso es relativamente independiente de otros subprocesos, hay menos posibilidades de que una instrucción en una etapa del pipeline necesite una salida de una instrucción anterior en el pipeline. Conceptualmente, es similar a la multitarea preventiva utilizada en los sistemas operativos; una analogía sería que la porción de tiempo asignada a cada subproceso activo es un ciclo de CPU.
Por ejemplo:
Este tipo de subprocesamiento múltiple se denominó inicialmente procesamiento de barril, en el que las etapas de un barril representan las etapas de la cadena de procesamiento y sus subprocesos de ejecución. Los subprocesos múltiples intercalados, preventivos, de grano fino o con intervalos de tiempo son términos más modernos.
Además de los costos de hardware que se analizaron en el tipo de bloque de subprocesos múltiples, el subproceso múltiple intercalado tiene un costo adicional: cada etapa de la secuencia de comandos realiza un seguimiento del identificador de subproceso de la instrucción que está procesando. Además, dado que hay más subprocesos que se ejecutan simultáneamente en la secuencia de comandos, los recursos compartidos, como las memorias caché y las TLB, deben ser más grandes para evitar la confusión entre los diferentes subprocesos.
El tipo más avanzado de subprocesamiento múltiple se aplica a los procesadores superescalares . Mientras que un procesador superescalar normal emite múltiples instrucciones desde un único subproceso en cada ciclo de CPU, en el subprocesamiento múltiple simultáneo (SMT) un procesador superescalar puede emitir instrucciones desde múltiples subprocesos en cada ciclo de CPU. Al reconocer que cualquier subproceso individual tiene una cantidad limitada de paralelismo a nivel de instrucción , este tipo de subproceso múltiple intenta explotar el paralelismo disponible en múltiples subprocesos para disminuir el desperdicio asociado con los espacios de emisión no utilizados.
Por ejemplo:
Para distinguir los otros tipos de multiprocesamiento de SMT, se utiliza el término " multiprocesamiento temporal " para indicar cuándo se pueden emitir instrucciones desde un solo hilo a la vez.
Además de los costos de hardware que se analizaron para el procesamiento multihilo intercalado, SMT tiene el costo adicional de que cada etapa de la secuencia de comandos realice un seguimiento del identificador de hilo de cada instrucción que se procesa. Nuevamente, los recursos compartidos, como las memorias caché y las TLB, deben dimensionarse para la gran cantidad de hilos activos que se procesan.
Las implementaciones incluyen DEC (más tarde Compaq ) EV8 (no completado), Intel Hyper-Threading Technology , IBM POWER5 / POWER6 / POWER7 / POWER8 / POWER9 , IBM z13 / z14 / z15 , Sun Microsystems UltraSPARC T2 , Cray XMT y las microarquitecturas AMD Bulldozer y Zen .
Un área importante de investigación es el programador de subprocesos, que debe elegir rápidamente entre la lista de subprocesos listos para ejecutarse el siguiente, así como mantener las listas de subprocesos listos para ejecutarse y los que están estancados. Un subtema importante son los diferentes esquemas de prioridad de subprocesos que puede utilizar el programador. El programador de subprocesos puede implementarse totalmente en software, totalmente en hardware o como una combinación de hardware y software.
Otra área de investigación es qué tipo de eventos deberían provocar un cambio de hilo: errores de caché, comunicación entre hilos, finalización de DMA , etc.
Si el esquema de subprocesamiento múltiple replica todo el estado visible del software, incluidos los registros de control privilegiados y las TLB, entonces permite que se creen máquinas virtuales para cada subproceso. Esto permite que cada subproceso ejecute su propio sistema operativo en el mismo procesador. Por otro lado, si solo se guarda el estado del modo de usuario, se requiere menos hardware, lo que permitiría que más subprocesos estén activos al mismo tiempo por la misma área de matriz o costo.