Una sola instrucción, múltiples datos ( SIMD ) es un tipo de procesamiento paralelo en la taxonomía de Flynn . SIMD puede ser interno (parte del diseño del hardware) y puede ser directamente accesible a través de una arquitectura de conjunto de instrucciones (ISA), pero no debe confundirse con una ISA. SIMD describe computadoras con múltiples elementos de procesamiento que realizan la misma operación en múltiples puntos de datos simultáneamente.
Estas máquinas explotan el paralelismo a nivel de datos , pero no la concurrencia : hay cálculos simultáneos (en paralelo), pero cada unidad realiza exactamente la misma instrucción en un momento dado (solo que con diferentes datos). SIMD es particularmente aplicable a tareas comunes como ajustar el contraste en una imagen digital o ajustar el volumen de audio digital . La mayoría de los diseños de CPU modernos incluyen instrucciones SIMD para mejorar el rendimiento del uso multimedia . SIMD tiene tres subcategorías diferentes en la Taxonomía de Flynn de 1972 , una de las cuales es SIMT . SIMT no debe confundirse con los subprocesos de software o los subprocesos de hardware , los cuales son tareas de tiempo compartido (fragmentación de tiempo). SIMT es una verdadera ejecución simultánea paralela a nivel de hardware.
Las unidades de procesamiento de gráficos (GPU) modernas suelen ser implementaciones SIMD amplias. [ cita requerida ]
El primer uso de instrucciones SIMD fue en el ILLIAC IV , que se completó en 1966.
SIMD fue la base de las supercomputadoras vectoriales de principios de los años 70, como la CDC Star-100 y la Texas Instruments ASC , que podían operar sobre un "vector" de datos con una sola instrucción. El procesamiento vectorial fue especialmente popularizado por Cray en los años 70 y 80. Las arquitecturas de procesamiento vectorial ahora se consideran separadas de las computadoras SIMD: la Taxonomía de Duncan las incluye, mientras que la Taxonomía de Flynn no, debido a que el trabajo de Flynn (1966, 1972) es anterior al Cray-1 (1977).
La primera era de las computadoras SIMD modernas se caracterizó por supercomputadoras de procesamiento masivo en paralelo, como las Thinking Machines CM-1 y CM-2 . Estas computadoras tenían muchos procesadores de funcionalidad limitada que trabajaban en paralelo. Por ejemplo, cada uno de los 65.536 procesadores de un solo bit en una Thinking Machines CM-2 ejecutaba la misma instrucción al mismo tiempo, lo que permitía, por ejemplo, combinar lógicamente 65.536 pares de bits a la vez, utilizando una red conectada a un hipercubo o una RAM dedicada al procesador para encontrar sus operandos. La supercomputación se alejó del enfoque SIMD cuando los enfoques MIMD escalares económicos basados en procesadores básicos como el Intel i860 XP se volvieron más potentes y el interés en SIMD disminuyó. [2]
La era actual de procesadores SIMD surgió del mercado de computadoras de escritorio, más que del mercado de supercomputadoras. A medida que los procesadores de escritorio se volvieron lo suficientemente potentes como para admitir juegos en tiempo real y procesamiento de audio/video durante la década de 1990, aumentó la demanda de este tipo particular de potencia de procesamiento y los proveedores de microprocesadores recurrieron a SIMD para satisfacer la demanda. [3] Hewlett-Packard introdujo instrucciones MAX en las computadoras de escritorio PA-RISC 1.1 en 1994 para acelerar la decodificación MPEG. [4] Sun Microsystems introdujo instrucciones de números enteros SIMD en sus extensiones del conjunto de instrucciones " VIS " en 1995, en su microprocesador UltraSPARC I. MIPS siguió su ejemplo con su sistema MDMX similar .
El primer SIMD de escritorio ampliamente implementado fue con las extensiones MMX de Intel para la arquitectura x86 en 1996. Esto provocó la introducción del sistema AltiVec mucho más poderoso en los sistemas Motorola PowerPC y POWER de IBM . Intel respondió en 1999 con la introducción del nuevo sistema SSE . Desde entonces, ha habido varias extensiones de los conjuntos de instrucciones SIMD para ambas arquitecturas. Las extensiones vectoriales avanzadas AVX, AVX2 y AVX-512 son desarrolladas por Intel. AMD admite AVX, AVX2 y AVX-512 en sus productos actuales. [5]
Todos estos desarrollos se han orientado al soporte de gráficos en tiempo real y, por lo tanto, están orientados al procesamiento en dos, tres o cuatro dimensiones, generalmente con longitudes de vector de entre dos y dieciséis palabras, dependiendo del tipo de datos y la arquitectura. Cuando es necesario distinguir las nuevas arquitecturas SIMD de las antiguas, las arquitecturas más nuevas se consideran arquitecturas de "vector corto", ya que las supercomputadoras SIMD y vectoriales anteriores tenían longitudes de vector de 64 a 64.000. Una supercomputadora moderna es casi siempre un grupo de computadoras MIMD, cada una de las cuales implementa instrucciones SIMD (de vector corto).
Una aplicación que puede aprovechar SIMD es aquella en la que se suma (o resta) el mismo valor a una gran cantidad de puntos de datos, una operación común en muchas aplicaciones multimedia . Un ejemplo sería cambiar el brillo de una imagen. Cada píxel de una imagen consta de tres valores para el brillo de las partes roja (R), verde (G) y azul (B) del color. Para cambiar el brillo, los valores R, G y B se leen de la memoria, se les suma (o se les resta) un valor y los valores resultantes se vuelven a escribir en la memoria. Los DSP de audio también multiplicarían, para el control del volumen, los canales izquierdo y derecho simultáneamente.
Con un procesador SIMD, este proceso presenta dos mejoras. Por un lado, los datos se entienden en bloques y se pueden cargar varios valores a la vez. En lugar de una serie de instrucciones que digan "recupere este píxel, ahora recupere el siguiente", un procesador SIMD tendrá una única instrucción que diga efectivamente "recupere n píxeles" (donde n es un número que varía de un diseño a otro). Por diversas razones, esto puede llevar mucho menos tiempo que recuperar cada píxel individualmente, como ocurre con un diseño de CPU tradicional.
Otra ventaja es que la instrucción opera sobre todos los datos cargados en una sola operación. En otras palabras, si el sistema SIMD funciona cargando ocho puntos de datos a la vez, la add
operación que se aplica a los datos se realizará sobre los ocho valores al mismo tiempo. Este paralelismo es independiente del paralelismo proporcionado por un procesador superescalar ; los ocho valores se procesan en paralelo incluso en un procesador no superescalar, y un procesador superescalar puede ser capaz de realizar múltiples operaciones SIMD en paralelo.
Para solucionar los problemas 1 y 5, la extensión vectorial de RISC-V utiliza un enfoque alternativo: en lugar de exponer los detalles a nivel de subregistro al programador, el conjunto de instrucciones los abstrae como unos pocos "registros vectoriales" que utilizan las mismas interfaces en todas las CPU con este conjunto de instrucciones. El hardware se encarga de todos los problemas de alineación y de la "extracción de datos" de los bucles. Las máquinas con distintos tamaños de vector podrían ejecutar el mismo código. LLVM llama a este tipo de vector "vscale". [ cita requerida ]
No es raro que se produzca un aumento de un orden de magnitud en el tamaño del código en comparación con un código escalar equivalente o un código vectorial equivalente, y se puede lograr un orden de magnitud o mayor de efectividad (trabajo realizado por instrucción) con las ISA vectoriales. [6]
La extensión vectorial escalable de ARM adopta otro enfoque, conocido en la taxonomía de Flynn como "procesamiento asociativo", más comúnmente conocido hoy como SIMD "predicado" (enmascarado) . Este enfoque no es tan compacto como el procesamiento vectorial , pero es mucho mejor que el SIMD no predicado. Se ofrecen ejemplos comparativos detallados en la página de procesamiento vectorial .
El SIMD de pequeña escala (64 o 128 bits) se hizo popular en las CPU de propósito general a principios de la década de 1990 y continuó hasta 1997 y más tarde con Motion Video Instructions (MVI) para Alpha . Las instrucciones SIMD se pueden encontrar, en un grado u otro, en la mayoría de las CPU, incluyendo AltiVec y SPE de IBM para PowerPC , PA-RISC Multimedia Acceleration eXtensions (MAX) de HP , MMX y iwMMXt de Intel , SSE , SSE2 , SSE3 SSSE3 y SSE4.x , 3DNow! de AMD , el subsistema de video ARC de ARC, VIS y VIS2 de SPARC , MAJC de Sun , la tecnología Neon de ARM , MDMX (MaDMaX) de MIPS y MIPS - 3D . El conjunto de instrucciones de la SPU del procesador Cell desarrollado conjuntamente por IBM, Sony y Toshiba se basa en gran medida en SIMD. Philips , ahora NXP , desarrolló varios procesadores SIMD llamados Xetal . El Xetal tiene 320 elementos de procesador de 16 bits especialmente diseñados para tareas de visión.
Las instrucciones SIMD AVX-512 de Intel procesan 512 bits de datos a la vez.
Las instrucciones SIMD se utilizan ampliamente para procesar gráficos 3D, aunque las tarjetas gráficas modernas con SIMD integrado han asumido en gran medida esta tarea de la CPU. Algunos sistemas también incluyen funciones de permutación que reempaquetan elementos dentro de vectores, lo que las hace particularmente útiles para el procesamiento y la compresión de datos. También se utilizan en criptografía. [7] [8] [9] La tendencia de la computación de propósito general en GPU ( GPGPU ) puede conducir a un uso más amplio de SIMD en el futuro.
La adopción de sistemas SIMD en el software de ordenadores personales fue lenta al principio, debido a una serie de problemas. Uno de ellos era que muchos de los primeros conjuntos de instrucciones SIMD tendían a ralentizar el rendimiento general del sistema debido a la reutilización de los registros de coma flotante existentes. Otros sistemas, como MMX y 3DNow!, ofrecían soporte para tipos de datos que no eran interesantes para un público amplio y tenían instrucciones de cambio de contexto costosas para cambiar entre el uso de los registros FPU y MMX . Los compiladores también solían carecer de soporte, lo que obligaba a los programadores a recurrir a la codificación en lenguaje ensamblador .
SIMD en x86 tuvo un comienzo lento. La introducción de 3DNow! por parte de AMD y SSE por parte de Intel confundió un poco las cosas, pero hoy el sistema parece haberse asentado (después de que AMD adoptara SSE) y los compiladores más nuevos deberían dar como resultado más software habilitado para SIMD. Intel y AMD ahora ofrecen bibliotecas matemáticas optimizadas que utilizan instrucciones SIMD, y han comenzado a aparecer alternativas de código abierto como libSIMD, SIMDx86 y SLEEF (ver también libm ). [10]
Apple Computer tuvo algo más de éxito, aunque entró en el mercado SIMD más tarde que el resto. AltiVec ofrecía un sistema rico y se puede programar utilizando compiladores cada vez más sofisticados de Motorola , IBM y GNU , por lo que rara vez se necesita programación en lenguaje ensamblador. Además, muchos de los sistemas que se beneficiarían de SIMD eran suministrados por la propia Apple, por ejemplo iTunes y QuickTime . Sin embargo, en 2006, las computadoras Apple se trasladaron a los procesadores Intel x86. Las API y las herramientas de desarrollo de Apple ( XCode ) se modificaron para admitir SSE2 y SSE3 , así como AltiVec. Apple fue el comprador dominante de chips PowerPC de IBM y Freescale Semiconductor . Aunque Apple ha dejado de utilizar procesadores PowerPC en sus productos, se continúa con el desarrollo de AltiVec en varios diseños PowerPC y Power ISA de Freescale e IBM.
SIMD dentro de un registro , o SWAR , es una serie de técnicas y trucos que se utilizan para realizar SIMD en registros de propósito general en hardware que no proporciona ningún soporte directo para instrucciones SIMD. Esto se puede utilizar para explotar el paralelismo en ciertos algoritmos incluso en hardware que no admite SIMD directamente.
Es habitual que los editores de conjuntos de instrucciones SIMD creen sus propias extensiones de lenguaje C/C++ con funciones intrínsecas o tipos de datos especiales (con sobrecarga de operadores ) que garantizan la generación de código vectorial. Intel, AltiVec y ARM NEON proporcionan extensiones ampliamente adoptadas por los compiladores destinados a sus CPU. (Las operaciones más complejas son tarea de las bibliotecas de matemáticas vectoriales).
El compilador GNU C lleva las extensiones un paso más allá al abstraerlas en una interfaz universal que se puede usar en cualquier plataforma al proporcionar una forma de definir tipos de datos SIMD. [11] El compilador LLVM Clang también implementa la característica, con una interfaz análoga definida en el IR. [12] La caja de Rust packed_simd
(y la experimental std::sims
) usa esta interfaz, y también lo hace Swift 2.0+.
C++ tiene una interfaz experimental std::experimental::simd
que funciona de manera similar a la extensión GCC. La biblioteca libcxx de LLVM parece implementarla. [ cita requerida ] Para GCC y libstdc++, está disponible una biblioteca contenedora que se basa en la extensión GCC. [13]
Microsoft agregó SIMD a .NET en RyuJIT. [14] El System.Numerics.Vector
paquete, disponible en NuGet, implementa tipos de datos SIMD. [15] Java también tiene una nueva API propuesta para instrucciones SIMD disponible en OpenJDK 17 en un módulo de incubación. [16] También tiene un mecanismo de respaldo seguro en CPU no compatibles para bucles simples.
En lugar de proporcionar un tipo de datos SIMD, también se puede indicar a los compiladores que vectoricen automáticamente algunos bucles, lo que podría dar lugar a algunas afirmaciones sobre la falta de dependencia de los datos. Esto no es tan flexible como manipular directamente las variables SIMD, pero es más fácil de usar. OpenMP 4.0+ tiene una #pragma omp simd
indicación. [17] Esta interfaz OpenMP ha reemplazado a un amplio conjunto de extensiones no estándar, incluidas las de Cilk#pragma simd
, [18] las de GCC #pragma GCC ivdep
y muchas más. [19]
Por lo general, se espera que el software de consumo funcione en una variedad de CPU que abarcan varias generaciones, lo que podría limitar la capacidad del programador para usar nuevas instrucciones SIMD para mejorar el rendimiento computacional de un programa. La solución es incluir varias versiones del mismo código que use tecnologías SIMD más antiguas o más nuevas, y elegir la que mejor se adapte a la CPU del usuario en tiempo de ejecución ( despacho dinámico ). Hay dos tipos principales de soluciones:
FMV, codificado manualmente en lenguaje ensamblador, se usa con bastante frecuencia en varias bibliotecas críticas para el rendimiento, como glibc y libjpeg-turbo. Intel C++ Compiler , GNU Compiler Collection desde GCC 6 y Clang desde clang 7 permiten un enfoque simplificado, en el que el compilador se encarga de la duplicación y selección de funciones. GCC y clang requieren target_clones
etiquetas explícitas en el código para "clonar" funciones, [20] mientras que ICC lo hace automáticamente (bajo la opción de línea de comandos /Qax
). El lenguaje de programación Rust también admite FMV. La configuración es similar a GCC y Clang en que el código define para qué conjuntos de instrucciones compilar, pero la clonación se realiza manualmente mediante la inserción en línea. [21]
Como el uso de FMV requiere la modificación del código en GCC y Clang, los proveedores suelen utilizar versiones múltiples de bibliotecas: esto es más fácil de lograr ya que solo es necesario cambiar los parámetros del compilador. Glibc admite LMV y esta funcionalidad es adoptada por el proyecto Clear Linux respaldado por Intel. [22]
En 2013, John McCutchan anunció que había creado una interfaz de alto rendimiento para conjuntos de instrucciones SIMD para el lenguaje de programación Dart , lo que permitió incorporar por primera vez los beneficios de SIMD a los programas web. La interfaz consta de dos tipos: [23]
Las instancias de estos tipos son inmutables y en el código optimizado se asignan directamente a los registros SIMD. Las operaciones expresadas en Dart normalmente se compilan en una sola instrucción sin ninguna sobrecarga. Esto es similar a las características intrínsecas de C y C++. Los puntos de referencia para la multiplicación de matrices 4×4 , la transformación de vértices 3D y la visualización de conjuntos de Mandelbrot muestran una aceleración cercana al 400 % en comparación con el código escalar escrito en Dart.
El trabajo de McCutchan en Dart, ahora llamado SIMD.js, ha sido adoptado por ECMAScript e Intel anunció en IDF 2013 que están implementando la especificación de McCutchan tanto para V8 como para SpiderMonkey . [24] Sin embargo, en 2017, SIMD.js se eliminó de la cola del estándar ECMAScript a favor de buscar una interfaz similar en WebAssembly . [25] A agosto de 2020, la interfaz de WebAssembly sigue sin terminar, pero su función SIMD portátil de 128 bits ya ha tenido algún uso en muchos motores.
Emscripten, el compilador C/C++ a JavaScript de Mozilla, con extensiones puede permitir la compilación de programas C++ que utilizan intrínsecos SIMD o código vectorial de estilo GCC para la API SIMD de JavaScript, lo que da como resultado aceleraciones equivalentes en comparación con el código escalar. [26] También admite (y ahora prefiere) la propuesta SIMD de 128 bits de WebAssembly. [27]
En general, ha resultado difícil encontrar aplicaciones comerciales sostenibles para procesadores que solo utilizan SIMD.
Uno de los que ha tenido cierto éxito es el GAPP , desarrollado por Lockheed Martin y llevado al sector comercial por su filial Teranex. Las encarnaciones recientes del GAPP se han convertido en una herramienta poderosa en aplicaciones de procesamiento de video en tiempo real como la conversión entre varios estándares de video y velocidades de cuadro ( NTSC a/desde PAL , NTSC a/desde formatos HDTV , etc.), desentrelazado , reducción de ruido de imagen , compresión de video adaptativa y mejora de imagen.
Una aplicación más ubicua para SIMD se encuentra en los videojuegos : casi todas las consolas de videojuegos modernas desde 1998 han incorporado un procesador SIMD en algún lugar de su arquitectura. La PlayStation 2 era inusual en el sentido de que una de sus unidades de vector-float podía funcionar como un DSP autónomo ejecutando su propio flujo de instrucciones, o como un coprocesador impulsado por instrucciones de CPU ordinarias. Las aplicaciones de gráficos 3D tienden a prestarse bien al procesamiento SIMD, ya que dependen en gran medida de operaciones con vectores de 4 dimensiones. Direct3D 9.0 de Microsoft ahora elige en tiempo de ejecución implementaciones específicas del procesador de sus propias operaciones matemáticas, incluido el uso de instrucciones con capacidad SIMD.
Un procesador posterior que utilizó procesamiento vectorial es el procesador Cell utilizado en la Playstation 3, desarrollado por IBM en cooperación con Toshiba y Sony . Utiliza varios procesadores SIMD (una arquitectura NUMA , cada uno con almacenamiento local independiente y controlado por una CPU de propósito general) y está orientado a los enormes conjuntos de datos requeridos por las aplicaciones de procesamiento de video y 3D. Se diferencia de los ISA tradicionales al ser SIMD desde el principio sin registros escalares separados.
Ziilabs produjo un procesador tipo SIMD para su uso en dispositivos móviles, como reproductores multimedia y teléfonos móviles. [28]
ClearSpeed Technology, Ltd. y Stream Processors, Inc. ofrecen procesadores SIMD comerciales de mayor escala. El CSX600 (2004) de ClearSpeed tiene 96 núcleos, cada uno con dos unidades de coma flotante de doble precisión, mientras que el CSX700 (2008) tiene 192. Stream Processors está dirigido por el arquitecto informático Bill Dally . Su procesador Storm-1 (2007) contiene 80 núcleos SIMD controlados por una CPU MIPS.