Hilo (informática)
En informática, un hilo de ejecución es la secuencia más pequeña de instrucciones programadas que puede gestionar de forma independiente un programador, que normalmente forma parte del sistema operativo. La implementación de subprocesos y procesos difiere entre sistemas operativos. En Modern Operating Systems, Tanenbaum muestra que son posibles muchos modelos distintos de organización de procesos. En muchos casos, un subproceso es un componente de un proceso. Los subprocesos múltiples de un proceso dado pueden ejecutarse simultáneamente (a través de capacidades de subprocesos múltiples), compartiendo recursos como la memoria, mientras que diferentes procesos no comparten estos recursos. En particular, los subprocesos de un proceso comparten su código ejecutable y los valores de sus variables asignadas dinámicamente y las variables globales no locales del subproceso en un momento dado.
Historia
Los subprocesos aparecieron pronto con el nombre de "tareas" en OS/360 Multiprogramming with a Variable Number of Tasks (MVT) en 1967. Saltzer (1966) acredita a Victor A. Vyssotsky con el término "hilo".
El uso de subprocesos en las aplicaciones de software se volvió más común a principios de la década de 2000 cuando las CPU comenzaron a utilizar varios núcleos. Las aplicaciones que deseaban aprovechar múltiples núcleos para obtener ventajas de rendimiento debían emplear la concurrencia para utilizar los múltiples núcleos.
Procesos, subprocesos del núcleo, subprocesos de usuario y fibras
La programación se puede realizar a nivel de kernel o de usuario, y la multitarea se puede realizar de forma preventiva o cooperativa. Esto produce una variedad de conceptos relacionados.
Procesos
A nivel del kernel, un proceso contiene uno o más subprocesos del kernel, que comparten los recursos del proceso, como la memoria y los identificadores de archivos: un proceso es una unidad de recursos, mientras que un subproceso es una unidad de programación y ejecución. La programación del kernel generalmente se realiza de manera uniforme de manera preventiva o, con menos frecuencia, de manera cooperativa. A nivel de usuario, un proceso como un sistema de tiempo de ejecución puede programar múltiples subprocesos de ejecución. Si estos no comparten datos, como en Erlang, por lo general se denominan procesos de manera análoga, mientras que si comparten datos, generalmente se denominan subprocesos (de usuario), especialmente si se programan de forma preventiva. Los subprocesos de usuario programados de forma cooperativa se conocen como fibras; diferentes procesos pueden programar subprocesos de usuario de manera diferente. Los subprocesos de usuario pueden ser ejecutados por subprocesos del kernel de varias maneras (uno a uno, muchos a uno, muchos a muchos). El término "proceso ligero" se refiere de diversas formas a hilos de usuario oa mecanismos del kernel para programar hilos de usuario en hilos del kernel.
Un proceso es un "peso pesado" unidad de programación del kernel, ya que crear, destruir y cambiar procesos es relativamente costoso. Procesa los recursos propios asignados por el sistema operativo. Los recursos incluyen memoria (tanto para código como para datos), identificadores de archivos, sockets, identificadores de dispositivos, ventanas y un bloque de control de procesos. Los procesos están aislados mediante el aislamiento de procesos y no comparten espacios de direcciones ni recursos de archivo, excepto a través de métodos explícitos, como heredar identificadores de archivo o segmentos de memoria compartidos, o mapear el mismo archivo de forma compartida; consulte la comunicación entre procesos.. Crear o destruir un proceso es relativamente costoso, ya que se deben adquirir o liberar recursos. Los procesos suelen ser multitareas preventivas, y el cambio de proceso es relativamente costoso, más allá del costo básico del cambio de contexto, debido a problemas como el vaciado de caché (en particular, el cambio de proceso cambia el direccionamiento de la memoria virtual, lo que provoca la invalidación y, por lo tanto, el vaciado de un búfer de búsqueda de traducción sin etiquetar, especialmente en x86).
Hilos del núcleo
Un hilo del núcleo es un "ligero" unidad de programación del núcleo. Existe al menos un subproceso del núcleo dentro de cada proceso. Si existen varios subprocesos del kernel dentro de un proceso, comparten la misma memoria y recursos de archivo. Los subprocesos del kernel realizan múltiples tareas de manera preventiva si el programador de procesos del sistema operativo es preventivo. Los subprocesos del kernel no poseen recursos excepto una pila, una copia de los registros que incluye el contador del programa y el almacenamiento local del subproceso (si lo hay), y por lo tanto son relativamente baratos de crear y destruir. El cambio de subprocesos también es relativamente económico: requiere un cambio de contexto (guardar y restaurar registros y puntero de pila), pero no cambia la memoria virtual y, por lo tanto, es compatible con caché (dejando TLB válido). El kernel puede asignar un subproceso a cada núcleo lógico de un sistema (porque cada procesador se divide en varios núcleos lógicos si es compatible con subprocesos múltiples, o solo admite un núcleo lógico por núcleo físico si no es así), y puede intercambiar subprocesos que quedar bloqueado Sin embargo, los subprocesos del kernel tardan mucho más en intercambiarse que los subprocesos del usuario.
Hilos de usuario
Los subprocesos a veces se implementan en bibliotecas de espacio de usuario, por lo que se denominan subprocesos de usuario. El kernel no los reconoce, por lo que se administran y programan en el espacio de usuario. Algunas implementaciones basan sus subprocesos de usuario sobre varios subprocesos del núcleo, para beneficiarse de las máquinas multiprocesador (modelo M:N). Los subprocesos de usuario implementados por máquinas virtuales también se denominan subprocesos verdes.
Como las implementaciones de subprocesos de usuario suelen estar completamente en el espacio de usuario, el cambio de contexto entre subprocesos de usuario dentro del mismo proceso es extremadamente eficiente porque no requiere ninguna interacción con el kernel: se puede realizar un cambio de contexto guardando localmente los registros de la CPU utilizado por el subproceso o la fibra del usuario que se está ejecutando actualmente y luego cargar los registros requeridos por el subproceso o la fibra del usuario para ejecutarse. Dado que la programación se realiza en el espacio del usuario, la política de programación se puede adaptar más fácilmente a los requisitos de la carga de trabajo del programa.
Sin embargo, el uso de bloqueo de llamadas al sistema en subprocesos de usuario (a diferencia de los subprocesos del kernel) puede ser problemático. Si un subproceso de usuario o una fibra realiza una llamada al sistema que bloquea, los otros subprocesos y fibras de usuario en el proceso no podrán ejecutarse hasta que regrese la llamada al sistema. Un ejemplo típico de este problema es cuando se realizan operaciones de E/S: la mayoría de los programas están escritos para realizar operaciones de E/S sincrónicamente. Cuando se inicia una operación de E/S, se realiza una llamada al sistema y no regresa hasta que se haya completado la operación de E/S. En el período intermedio, todo el proceso está "bloqueado" por el kernel y no puede ejecutarse, lo que impide que otros subprocesos y fibras del usuario se ejecuten en el mismo proceso.
Una solución común a este problema (usada, en particular, por muchas implementaciones de subprocesos verdes) es proporcionar una API de E/S que implementa una interfaz que bloquea el subproceso de llamada, en lugar de todo el proceso, mediante el uso de I sin bloqueo. /O internamente y programar otro subproceso o fibra de usuario mientras la operación de E/S está en curso. Se pueden proporcionar soluciones similares para otras llamadas al sistema de bloqueo. Alternativamente, el programa se puede escribir para evitar el uso de E/S sincrónicas u otras llamadas al sistema de bloqueo (en particular, usando E/S sin bloqueo, incluidas continuaciones lambda y/o primitivas asíncronas/en espera).
Fibras
Las fibras son una unidad de programación aún más liviana que se programan cooperativamente: una fibra en funcionamiento debe "rendir" para permitir que se ejecute otra fibra, lo que hace que su implementación sea mucho más fácil que los hilos del núcleo o del usuario. Se puede programar una fibra para que se ejecute en cualquier subproceso en el mismo proceso. Esto permite que las aplicaciones obtengan mejoras en el rendimiento administrando la programación por sí mismas, en lugar de confiar en el programador del kernel (que puede no estar ajustado para la aplicación). En ocasiones, los entornos de programación paralelos, como OpenMP, implementan sus tareas a través de fibras. Estrechamente relacionadas con las fibras están las corrutinas, con la distinción de que las corrutinas son una construcción a nivel de lenguaje, mientras que las fibras son una construcción a nivel de sistema.
Hilos frente a procesos
Los subprocesos se diferencian de los procesos multitarea tradicionales del sistema operativo en varios aspectos:
- los procesos son típicamente independientes, mientras que los hilos existen como subconjuntos de un proceso
- procesos llevan considerablemente más información estatal que los hilos, mientras que múltiples hilos dentro de un estado de proceso de compartir, así como memoria y otros recursos
- procesos tienen espacios de dirección separados, mientras que los hilos comparten su espacio de dirección
- los procesos sólo interactúan mediante mecanismos de comunicación entre procesos proporcionados por el sistema
- el cambio de contexto entre los hilos en el mismo proceso normalmente ocurre más rápido que el cambio de contexto entre los procesos
Se dice que los sistemas como Windows NT y OS/2 tienen subprocesos baratos y procesos caros; en otros sistemas operativos no hay una diferencia tan grande, excepto en el costo de un cambio de espacio de direcciones, que en algunas arquitecturas (sobre todo x86) da como resultado un vaciado del búfer de búsqueda lateral de traducción (TLB).
Las ventajas y desventajas de los subprocesos frente a los procesos incluyen:
- Menor consumo de recursos de hilos: el uso de hilos, una aplicación puede operar utilizando menos recursos de lo que necesitaría al utilizar múltiples procesos.
- Intercambio y comunicación simplificados de hilos: a diferencia de los procesos, que requieren un mensaje que pasa o un mecanismo de memoria compartido para realizar la comunicación entre procesos (IPC), los hilos pueden comunicarse a través de datos, código y archivos que ya comparten.
- El pan choca un proceso: debido a los hilos que comparten el mismo espacio de dirección, una operación ilegal realizada por un hilo puede chocar todo el proceso; por lo tanto, un hilo de mala conducta puede interrumpir el procesamiento de todos los demás hilos en la aplicación.
Programación
Programación preventiva frente a cooperativa
Los sistemas operativos programan subprocesos de forma preventiva o cooperativa. Los sistemas operativos multiusuario generalmente favorecen los subprocesos múltiples preventivos por su control más detallado sobre el tiempo de ejecución a través del cambio de contexto. Sin embargo, la programación preventiva puede cambiar el contexto de los subprocesos en momentos no previstos por los programadores, lo que provoca bloqueos de convoy, inversión de prioridad u otros efectos secundarios. Por el contrario, los subprocesos múltiples cooperativos se basan en subprocesos para ceder el control de la ejecución, lo que garantiza que los subprocesos se ejecuten hasta su finalización. Esto puede causar problemas si un subproceso multitarea cooperativo se bloquea al esperar un recurso o si priva a otros subprocesos al no ceder el control de la ejecución durante un cómputo intensivo.
Sistemas de uno o varios procesadores
Hasta principios de la década de 2000, la mayoría de las computadoras de escritorio tenían solo una CPU de un solo núcleo, sin soporte para subprocesos de hardware, aunque los subprocesos todavía se usaban en tales computadoras porque el cambio entre subprocesos generalmente era más rápido que los cambios de contexto de proceso completo. En 2002, Intel agregó soporte para subprocesos múltiples simultáneos al procesador Pentium 4, bajo el nombre hiper-proceso; en 2005, presentaron el procesador Pentium D de doble núcleo y AMD presentó el procesador Athlon 64 X2 de doble núcleo.
Los sistemas con un solo procesador generalmente implementan subprocesos múltiples por división de tiempo: la unidad central de procesamiento (CPU) cambia entre diferentes procesos de software. Este cambio de contexto generalmente ocurre con la frecuencia suficiente para que los usuarios perciban que los subprocesos o las tareas se ejecutan en paralelo (para los sistemas operativos populares de servidor/escritorio, el intervalo de tiempo máximo de un subproceso, cuando otros subprocesos están esperando, a menudo se limita a 100-200 ms). En un sistema multiprocesador o multinúcleo, varios subprocesos pueden ejecutarse en paralelo, con cada procesador o núcleo ejecutando un subproceso separado simultáneamente; en un procesador o núcleo con subprocesos de hardware, los subprocesos de software separados también pueden ejecutarse simultáneamente por subprocesos de hardware separados.
Modelos de roscado
1:1 (subprocesamiento a nivel de kernel)
Los subprocesos creados por el usuario en una correspondencia 1:1 con entidades programables en el kernel son la implementación de subprocesos más simple posible. OS/2 y Win32 usaron este enfoque desde el principio, mientras que en Linux la biblioteca GNU C implementa este enfoque (a través de NPTL o LinuxThreads más antiguos). Este enfoque también lo utilizan Solaris, NetBSD, FreeBSD, macOS e iOS.
N:1 (subprocesamiento a nivel de usuario)
Un modelo N:1 implica que todos los subprocesos a nivel de aplicación se asignan a una entidad programada a nivel de kernel; el núcleo no tiene conocimiento de los subprocesos de la aplicación. Con este enfoque, el cambio de contexto se puede realizar muy rápidamente y, además, se puede implementar incluso en núcleos simples que no admiten subprocesos. Sin embargo, uno de los principales inconvenientes es que no puede beneficiarse de la aceleración de hardware en procesadores de subprocesos múltiples o computadoras con procesadores múltiples: nunca hay más de un subproceso programado al mismo tiempo. Por ejemplo: si uno de los subprocesos necesita ejecutar una solicitud de E/S, todo el proceso se bloquea y no se puede utilizar la ventaja de subprocesos. GNU Portable Threads utiliza subprocesos a nivel de usuario, al igual que State Threads.
M:N (hilo híbrido)
M:N mapea algunos M número de subprocesos de aplicación en algunos N número de entidades del núcleo o "procesadores virtuales." Este es un compromiso entre el nivel de kernel ("1:1") y el nivel de usuario ("N:1"). En general, "M:N" Los sistemas de subprocesos son más complejos de implementar que los subprocesos del kernel o del usuario, porque se requieren cambios tanto en el kernel como en el código del espacio del usuario. En la implementación M:N, la biblioteca de subprocesos es responsable de programar subprocesos de usuario en las entidades programables disponibles; esto hace que el cambio de contexto de los subprocesos sea muy rápido, ya que evita las llamadas al sistema. Sin embargo, esto aumenta la complejidad y la probabilidad de inversión de prioridades, así como una programación subóptima sin una coordinación extensa (y costosa) entre el programador del área de usuario y el programador del kernel.
Ejemplos de implementación híbrida
- Activaciones del programador utilizadas por versiones anteriores de la implementación de la biblioteca de hilos POSIX nativos de NetBSD (an M:N modelo a diferencia de un kernel 1:1 o modelo de implementación del espacio de usuario)
- Procesos ligeros utilizados por versiones antiguas del sistema operativo Solaris
- Marcel del proyecto PM2.
- El sistema operativo para el MTA-2 de Tera-Cray
- The Glasgow Haskell Compiler (GHC) for the language Haskell uses lightweight threads which are scheduled on operating system threads.
Historia de modelos de subprocesos en sistemas Unix
SunOS 4.x implementó procesos ligeros o LWP. NetBSD 2.x+ y DragonFly BSD implementan LWP como subprocesos del núcleo (modelo 1:1). SunOS 5.2 a SunOS 5.8, así como NetBSD 2 a NetBSD 4, implementaron un modelo de dos niveles, multiplexando uno o más subprocesos de nivel de usuario en cada subproceso del núcleo (modelo M:N). SunOS 5.9 y versiones posteriores, así como NetBSD 5, eliminaron la compatibilidad con subprocesos de usuario y volvieron a un modelo 1:1. FreeBSD 5 implementó el modelo M:N. FreeBSD 6 admitía tanto 1:1 como M:N, los usuarios podían elegir cuál usar con un programa dado usando /etc/libmap.conf. A partir de FreeBSD 7, el 1:1 se convirtió en el predeterminado. FreeBSD 8 ya no es compatible con el modelo M:N.
Programas de subproceso único frente a multiproceso
En la programación de computadoras, single-threading es el procesamiento de un comando a la vez. En el análisis formal de las variables' semántica y estado del proceso, el término subproceso único se puede usar de manera diferente para referirse a "retroceder dentro de un solo subproceso", que es común en la comunidad de programación funcional.
Los subprocesos múltiples se encuentran principalmente en los sistemas operativos multitarea. Multithreading es un modelo generalizado de programación y ejecución que permite que existan múltiples hilos dentro del contexto de un proceso. Estos subprocesos comparten los recursos del proceso, pero pueden ejecutarse de forma independiente. El modelo de programación con subprocesos proporciona a los desarrolladores una abstracción útil de la ejecución concurrente. Los subprocesos múltiples también se pueden aplicar a un proceso para permitir la ejecución paralela en un sistema de procesamiento múltiple.
Las bibliotecas de subprocesos múltiples tienden a proporcionar una llamada de función para crear un nuevo subproceso, que toma una función como parámetro. Luego se crea un subproceso concurrente que comienza a ejecutar la función pasada y finaliza cuando la función regresa. Las bibliotecas de subprocesos también ofrecen funciones de sincronización de datos.
Hilos y sincronización de datos
Los subprocesos en el mismo proceso comparten el mismo espacio de direcciones. Esto permite que el código que se ejecuta simultáneamente se acople de forma estrecha y conveniente para intercambiar datos sin la sobrecarga o la complejidad de un IPC. Sin embargo, cuando se comparten entre subprocesos, incluso las estructuras de datos simples se vuelven propensas a condiciones de carrera si requieren más de una instrucción de CPU para actualizarse: dos subprocesos pueden terminar intentando actualizar la estructura de datos al mismo tiempo y descubrir que cambia inesperadamente. Los errores causados por las condiciones de carrera pueden ser muy difíciles de reproducir y aislar.
Para evitar esto, las interfaces de programación de aplicaciones (API) de subprocesos ofrecen primitivas de sincronización, como mutexes, para bloquear las estructuras de datos contra el acceso simultáneo. En los sistemas monoprocesador, un subproceso que se ejecuta en un mutex bloqueado debe dormir y, por lo tanto, desencadenar un cambio de contexto. En sistemas multiprocesador, el subproceso puede sondear el mutex en un spinlock. Ambos pueden mermar el rendimiento y obligar a los procesadores en sistemas de multiprocesamiento simétrico (SMP) a competir por el bus de memoria, especialmente si la granularidad del bloqueo es demasiado fina.
Otras API de sincronización incluyen variables de condición, secciones críticas, semáforos y monitores.
Grupos de subprocesos
Un patrón de programación popular que involucra subprocesos es el de grupos de subprocesos donde se crea un número determinado de subprocesos al inicio que luego esperan a que se les asigne una tarea. Cuando llega una nueva tarea, se despierta, completa la tarea y vuelve a esperar. Esto evita las funciones relativamente costosas de creación y destrucción de subprocesos para cada tarea realizada y saca la administración de subprocesos de la mano del desarrollador de la aplicación y lo deja en manos de una biblioteca o el sistema operativo que se adapta mejor para optimizar la administración de subprocesos.
Pros y contras de los programas multihilo frente a los programas de un solo hilo
Las aplicaciones multihilo tienen las siguientes ventajas frente a las de un solo hilo:
- Responsabilidad: Multithreading puede permitir que una aplicación siga siendo sensible a la entrada. En un programa de un hilo, si el hilo principal de ejecución bloquea una tarea de larga duración, toda la aplicación puede parecer congelada. Al mover tales tareas de larga duración a una hilo obrero que se ejecuta simultáneamente con el hilo de ejecución principal, es posible que la aplicación siga respondiendo a la entrada del usuario mientras realiza tareas en el fondo. Por otro lado, en la mayoría de los casos la multitelección no es la única manera de mantener un programa sensible, con las señales no bloqueantes I/O y/o Unix disponibles para obtener resultados similares.
- Paralelización: las aplicaciones que buscan utilizar sistemas multicore o multi-CPU pueden utilizar multithreading para dividir datos y tareas en subtaks paralelos y permitir que la arquitectura subyacente gestionar cómo funcionan los hilos, ya sea simultáneamente en un núcleo o en paralelo en múltiples núcleos. Los entornos de computación GPU como CUDA y OpenCL utilizan el modelo de multitelección donde decenas a cientos de hilos se ejecutan en paralelo a través de datos sobre un gran número de núcleos. Esto, a su vez, permite una mejor utilización del sistema, y (siempre que los costos de sincronización no comen los beneficios arriba), puede proporcionar una ejecución más rápida del programa.
Las aplicaciones multiproceso tienen los siguientes inconvenientes:
- Sincronización complejidad y errores relacionados: al utilizar recursos compartidos típicos para los programas en rosca, el programador debe tener cuidado de evitar las condiciones de carrera y otros comportamientos no intuitivos. Para que los datos sean manipulados correctamente, los hilos a menudo tendrán que citarse a tiempo para procesar los datos en el orden correcto. Los hilos también pueden requerir operaciones mutuamente excluyentes (a menudo implementadas usando mutexes) para evitar que los datos comunes sean leídos o sobrescritos en un hilo mientras se modifican por otro. El uso descuidado de tales primitivos puede llevar a estancamientos, candados o carreras sobre recursos. Como Edward A. Lee ha escrito: "Aunque los hilos parecen ser un pequeño paso de la computación secuencial, de hecho, representan un gran paso. Desechan las propiedades más esenciales y atractivas de la computación secuencial: comprensión, previsibilidad y determinismo. Los hilos, como modelo de computación, son salvajemente no-deterministas, y el trabajo del programador se convierte en uno de podar ese no-determinismo".
- Ser intestable. En general, los programas multiteleados no son deterministas, y como resultado, son intestables. En otras palabras, un programa multitreaded puede fácilmente tener errores que nunca se manifiestan en un sistema de prueba, manifestándose sólo en la producción. Esto puede aliviarse restringiendo las comunicaciones entre hilos a ciertos patrones bien definidos (como el paso de mensajes).
- Costos de sincronización. A medida que el interruptor de contexto de hilo en las CPU modernas puede costar hasta 1 millón de ciclos de CPU, hace difícil escribir programas eficientes de multitelección. En particular, hay que prestar especial atención a evitar que la sincronización entre los textos sea demasiado frecuente.
Soporte de lenguaje de programación
Muchos lenguajes de programación admiten subprocesos de alguna manera.
- IBM PL/I(F) incluyó el apoyo para la multiaplicación (llamado multitarea) tan temprano como a finales de la década de 1960, y esto continuó en el Compiler de Optimización y versiones posteriores. El compilador IBM Enterprise PL/I introdujo un nuevo modelo de API "pan". Ninguna versión era parte de la norma PL/I.
- Muchas implementaciones de C y C++ soportan la rosca, y proporcionan acceso a las APIs de rosca nativas del sistema operativo. Una interfaz estandarizada para la implementación de los hilos es POSIX Threads (Pthreads), que es un conjunto de llamadas de la biblioteca de funciones C. Los proveedores de OS son gratuitos para implementar la interfaz como se desee, pero el desarrollador de aplicaciones debe ser capaz de utilizar la misma interfaz en múltiples plataformas. La mayoría de las plataformas Unix, incluyendo Linux, soportan Pthreads. Microsoft Windows tiene su propio conjunto de funciones de hilo en el proceso.h interfaz para multithreading, como startthread.
- Algunos idiomas de programación de nivel superior (y generalmente multiplataforma), como Java, Python y. NET Framework languages, expose threading to developers while abstracting the platform specific differences in threading implementations in the runtime. Varios otros lenguajes de programación y extensiones de lenguaje también tratan de abstraer el concepto de concurrencia e rosca del desarrollador completamente (Cilk, OpenMP, Interfaz de Paso de Mensajes (MPI)). Algunos idiomas están diseñados para el paralelismo secuencial en su lugar (especialmente utilizando GPU), sin requerir concurrencia o hilos (Ateji PX, CUDA).
- Algunos idiomas de programación interpretados tienen implementaciones (por ejemplo, RM Ruby para Ruby, CPython para Python) que apoyan la rosca y la concurrencia pero no la ejecución paralela de los hilos, debido a un bloqueo de intérprete global (GIL). El GIL es un bloqueo de exclusión mutua mantenido por el intérprete que puede impedir que el intérprete interprete simultáneamente el código de aplicaciones en dos o más hilos de inmediato, lo que limita efectivamente el paralelismo en múltiples sistemas básicos. Esto limita el rendimiento principalmente para los hilos con procesadores, que requieren el procesador, y no mucho para los I/O-bound o de red. Otras implementaciones de lenguajes de programación interpretados, como Tcl usando la extensión Thread, evitan el límite GIL utilizando un modelo de apartamento donde los datos y el código deben ser "compartidos" explícitamente entre hilos. En Tcl cada hilo tiene uno o más intérpretes.
- En modelos de programación como CUDA diseñados para la computación paralela de datos, una serie de hilos ejecutan el mismo código en paralelo utilizando sólo su ID para encontrar sus datos en memoria. En esencia, la aplicación debe diseñarse para que cada hilo realice la misma operación en diferentes segmentos de memoria para que puedan operar en paralelo y utilizar la arquitectura GPU.
- Los lenguajes de descripción de hardware como Verilog tienen un modelo de rosca diferente que soporta un número extremadamente grande de hilos (para modelar hardware).
Contenido relacionado
RC4
Código de Manchester
VisiCalc