Arquitecturas de altas prestaciones
Índice
- Introducción
- Objetivos
- 1.Descomposición funcional y de datos
- 2.Taxonomía de Flynn
- 3.Arquitecturas de procesador SIMD
- 4.Arquitecturas de procesador multihilo o MIMD
- 4.1.Arquitecturas superthreading
- 4.1.1.Compartición a nivel fino
- 4.1.2.Compartición a nivel grueso
- 4.2.Arquitecturas simultaneous multithreading
- 4.3.Convirtiendo el paralelismo a nivel de hilo a paralelismo a nivel de instrucción
- 4.4.Diseño de un SMT
- 4.5.Complejidades y retos en las arquitecturas SMT
- 4.6.Arquitecturas multinúcleo
- 4.1.Arquitecturas superthreading
- 5.Arquitecturas many-core: el caso de Intel Xeon Phi
- 5.1.Historia de los Xeon Phi
- 5.2.Presentación de los Xeon KNC y KNF
- 5.3.Arquitectura y sistema de interconexión
- 5.4.Núcleos de los KNC
- 5.5.Sistema de coherencia
- 5.6.Protocolo de coherencia
- 5.7.Conclusiones
- 5.8.Knights Landing Xeon Phi
- 5.8.1.Red de interacción
- 5.8.2.Núcleos y modelos de coherencia
- 5.8.3.Subsistema de memoria
- 5.8.4.MCDRAM
- 5.8.5.DRAM (DDR)
- 5.8.6.Modos de memoria
- Resumen
- Actividades
- Bibliografía
Introducción
-
Técnicas asociadas a explotar el paralelismo de las instrucciones.
-
Técnicas asociadas a explotar el paralelismo a nivel de datos.
-
Técnicas asociadas a explotar el paralelismo de hilos de ejecución.
Objetivos
-
Estudiar qué es la taxonomía de Flyint y saber cómo se relaciona esta con las diferentes arquitecturas actuales.
-
Entender qué arquitecturas de computadores hay y cómo se pueden emplear en la computación de altas prestaciones.
-
Estudiar qué es el paralelismo a nivel de datos y saber cómo las aplicaciones pueden incrementar su rendimiento usando este paradigma. Y dentro de este ámbito, entender qué son las arquitecturas vectoriales y cómo funcionan.
-
Entender cuáles son los beneficios de usar arquitecturas que explotan el paralelismo a nivel de hilo.
-
Estudiar qué tipo de arquitecturas multihilo hay y conocer las propiedades de cada una de ellas.
-
Entender cómo se puede mejorar el rendimiento de los procesadores explotando el paralelismo a nivel de hilo y a nivel de instrucción conjuntamente.
-
Estudiar cuáles son los factores relacionados con el modelo de programación que hay que tener en cuenta a la hora de desarrollar aplicaciones multihilo.
-
Estudiar cuáles son los factores relacionados con la arquitectura de un procesador multihilo que hay que considerar en el desarrollo de aplicaciones multihilo.
-
Estudiar cuáles son las características del modelo de programación de memoria compartida y memoria distribuida.
1.Descomposición funcional y de datos
2.Taxonomía de Flynn
3.Arquitecturas de procesador SIMD
Parámetros: VectorEnteros[1024] A; VectorEnteros[1024] B; VectorEnteros[1024] C; Código: por(i = 0; i < 1024; i++) C[i] = A[i]+B[i]; Parámetros: VectorEnteros[1024] A; VectorEnteros[1024] B; VectorEnteros[1024] C; Código: RegistroVectorial512 a,b,c; Por(i=0; i<512; i+=16) { carga(a,A[i]); carga(b,B[i]); c = suma_vectorial(a,b); guarda(C[i],c); }
3.1.Propiedades de los procesadores vectoriales
3.2.Ejemplo de procesador vectorial
4.Arquitecturas de procesador multihilo o MIMD
-
Diferentes hilos de ejecución comparten las unidades funcionales del procesador (por ejemplo, unidades funcionales).
-
El procesador tiene que tener estructuras independientes para cada uno de los hilos que ejecuta: registro de renaming, contador de programa, etc.
-
Si los hilos pertenecen a diferentes procesos, el procesador tiene que facilitar mecanismos para que puedan trabajar con diferentes tablas de páginas.
4.1.Arquitecturas superthreading
4.1.1.Compartición a nivel fino
4.1.2.Compartición a nivel grueso
4.2.Arquitecturas simultaneous multithreading
4.3.Convirtiendo el paralelismo a nivel de hilo a paralelismo a nivel de instrucción
ciclo(n)hilo 1-->"LOAD #43,r3" ciclo(n+1)hilo 2-->"ADD r2,r3,r4" ciclo(n+2)hilo 1-->"ADD r4,r3,r2" ciclo(n+3)hilo 1-->"LOAD (r2),r4"
4.4.Diseño de un SMT
4.5.Complejidades y retos en las arquitecturas SMT
-
Mantener una lógica simple en las etapas que son fundamentales y que hay que ejecutar en un solo ciclo. Por ejemplo, en la elección de instrucción simple hay que tener presente que cuantos más hilos hay, la bolsa de instrucciones que se pueden escoger es más grande. Pasa lo mismo en la etapa de fin de instrucción, en la que el procesador tiene que escoger cuál de las instrucciones acabadas finalizarán en el próximo ciclo.
-
Tener diferentes hilos de ejecución implica que hay que tener un banco de registros suficientemente grande como para guardar cada uno de los contextos. Esto tiene implicaciones tanto de espacio como de consumo energético.
-
Uno de los problemas de tener diferentes hilos de ejecución compartiendo los recursos de un mismo procesador puede ser el acceso compartido a la memoria caché. Puede pasar que los mismos hilos hagan lo que se denomina falsa compartición, que es cuando hilos diferentes están compartiendo los mismos sets de la memoria caché, a pesar de que están accediendo a direcciones físicas diferentes. En los casos con mucha falsa compartición, el rendimiento del sistema se degrada de manera sustancial.
4.6.Arquitecturas multinúcleo
4.6.1.Limitaciones de la SMT y arquitecturas superthreading
Escalabilidad y complejidad
Consumo energético y área
4.6.2.Producción
4.6.3.El concepto de multinúcleo
4.6.4.Coherencia entre núcleos
instante(n) núcleo 1-->lectura @X =11 (L3-->L1/L2) instante(n+1) núcleo 1-->escritura @X=0 (L2) instante(n+2) núcleo 2-->lectura @X=11 (L3-->L1/L2) instante(n+3) núcleo 1-->escritura @X=0 (L2-->L3)
Interconexiones
4.6.5.Protocolos de coherencia
-
Si uno de los núcleos quiere hacer una lectura, recibe de ella la última copia. No puede darse el caso de que otro núcleo la esté modificando mientras este tiene una copia.
-
Cuando un núcleo pide una línea de memoria, la puede pedir en exclusiva o en estado compartido. El núcleo solo puede modificar la línea cuando esta la tenga en estado exclusivo. Entonces la línea se encuentra en estado modificado.
-
Dependiendo del modelo de coherencia que se use, dos núcleos pueden tener @X en las memorias caché respectivas en estado compartido. Ahora bien, no pueden modificar esta línea (porque entonces tendríamos dos valores diferentes de @X en dos núcleos).
-
Si uno de los núcleos quiere modificar el dato, antes hay que avisar al resto de núcleos que tienen que invalidar esta línea. Si otro núcleo la vuelve a querer, primero se tiene que escribir en la L3 o en memoria y este lo tiene que leer de L3. Dependiendo del protocolo, podemos encontrar ciertas variantes.
5.Arquitecturas many-core: el caso de Intel Xeon Phi
5.1.Historia de los Xeon Phi
5.2.Presentación de los Xeon KNC y KNF
5.3.Arquitectura y sistema de interconexión
-
El agente PCIe es el encargado de comunicarse con el host. Cada vez que uno de los núcleos accede al espacio de memoria que se encuentra mapeado en el host, la petición del núcleo acabará llegando al host a través de este agente. Del mismo modo, cada vez que el host quiere enviar datos o peticiones al KNC, lo hará usando este agente.
-
El agente núcleo es el encargado de llevar a cabo los cálculos y las acciones de los distintos hilos que la aplicación ha instanciado. Como ya se ha mencionado anteriormente, cada núcleo tiene cuatro hilos de ejecución y contiene dos niveles de memoria caché (más adelante, se presentan más detalles de esto).
-
El agente TD o tag directory se encarga de mantener la coherencia de memoria. Cada vez que un núcleo quiere acceder a una dirección de memoria, lo tiene que pedir al TD pues es el encargado de gestionar la coherencia de la dirección en cuestión. Cada dirección del espacio de memoria es gestionada por tan solo un TD. Como se verá más adelante, cuando este recibe una petición para acceder a un dato tiene que controlar que ningún otro núcleo lo tenga antes de pedirlo a memoria. En caso contrario, deberá notificarlo al núcleo que lo tenga para que este actualice su estado.
-
Finalmente, el último agente es el controlador de memoria. Este agente se encarga de satisfacer las peticiones de acceso a memoria principal que reciben del TD y que han sido originadas por uno de los núcleos. Cuando este recibe una petición de lectura o escritura, el controlador traduce esta petición a los pedidos específicos que el dispositivo de GDDR5 entiende. Para más información de cómo un controlador de memoria interacciona con un dispositivo GDDR5, se recomienda la lectura de la introducción a esta tecnología (Jedec).
-
Peticiones entre los diferentes agentes. Por ejemplo, la petición de una línea de memoria en exclusiva de un núcleo a un TD; o bien una petición de lectura de una línea de memoria de un TD a un controlador de memoria.
-
Datos que se envían entre los diferentes agentes y generados como consecuencia de una petición que se ha iniciado anteriormente. Por ejemplo, después de la petición de lectura de una línea de memoria por parte de un núcleo alguno de los controladores de memoria acabará enviando los datos pedidos al núcleo que ha enviado la petición.
-
Respuestas de confirmación o resultado que, como en el caso de los datos, han sido generadas como consecuencia de una petición. Por ejemplo, cuando un TD recibe una petición de lectura de una línea de memoria, este tiene que responder al núcleo que la transacción se está procesando correctamente y cuál es el estado con el que se retornará la línea en cuestión (exclusiva o compartida).
5.4.Núcleos de los KNC
Modelo |
Consumo (vatios) |
Número núcleos |
Frecuencia (GHZ) |
Rendimiento máximo (GFLops) |
Ancho de banda de memoria máximo (GB/s) |
Capacidad memoria |
---|---|---|---|---|---|---|
3120P |
300 |
57 |
1.1 |
1003 |
240 |
6 |
3120A |
300 |
57 |
1.1 |
1003 |
240 |
6 |
5110P |
225 |
60 |
1.053 |
1011 |
320 |
8 |
5120D |
245 |
60 |
1.053 |
1011 |
352 |
8 |
7110P |
300 |
61 |
1.238 |
1208 |
352 |
16 |
7120X |
300 |
61 |
1.238 |
1208 |
352 |
16 |
5.5.Sistema de coherencia
Estado |
Definición |
Propietarios de la línea |
Estado respecto a memoria |
---|---|---|---|
M |
Modificada |
Solo un núcleo es propietario de la línea. |
Modificada. |
E |
Exclusiva |
Solo un núcleo es propietario de la línea. |
No modificada. |
S |
Compartida |
Un conjunto de núcleos contienen la línea. |
Puede estar modificada o no. |
I |
Invalida |
Ningún núcleo contiene la línea. |
- |
Estado |
Definición |
Propietarios de la línea |
Estado respecto a memoria |
---|---|---|---|
GOLES |
Globally owned Locally Shared |
Diferentes núcleos la pueden tener. |
Modificada |
GM/GE |
Globally Modified / Exclusive |
Solo este núcleo la tiene. |
Puede estar modificada o no |
GS |
Globally Shared |
Diferentes núcleos la pueden tener. |
No ha sido modificada |
GI |
Globally Invalid |
Ningún núcleo contiene la línea. |
- |
5.6.Protocolo de coherencia
5.7.Conclusiones
5.8.Knights Landing Xeon Phi
-
Del mismo modo que las GPUS, KNC y KNF, estaban basadas en una conexión PCIe. Es decir, eran aceleradores conectados a unos procesadores a los que se podía hacer offloading de ciertas partes del código, las cuales se marcaban con directivas (pragmes).
-
Por el hecho de que están conectadas vía PCIe hace que no sean bootables. Es decir, que no puedan arrancar una aplicación que podría correr sobre un servidor x86 estándar. Por lo tanto, binarios que estén compilados para ser ejecutados sobre KNC o KNF tendrían que ser recompilados por otras arquitecturas x86 si fuera necesario.
-
Tal y como ya se ha comentado con el modelo de las GPU, los KNF y KNC (como modelo de aceleración) tienen una memoria propia que no es compartida con el procesador principal. Por lo tanto, cada vez que se quieren mover datos del procesador principal al KNF o KNC, hay que mover los datos de la memoria del huésped (Xeon) al KNC o KNF.
-
En cuanto a los modelos de coherencia y red de interconexión usada para conectar los diferentes componentes del procesador (directorios, núcleos, etc.), son similares a los que generaciones anteriores de procesadores Intel habían usado. Los modelos de coherencia eran un MOESIF con GOALS y la red de interconexión era un anillo bidireccional conectado por diferentes tipos de canales (uno para datos, uno para peticiones, etc.).
-
Los números de núcleos incluidos dentro de KNF y KNF eran sustancialmente más elevados que los procesadores Xeon existentes en aquella época para intentar maximizar al máximo el nivel de TLP que el procesador ofrece a la aplicación. Un Xeon estándar incluía sobre unos 8-12 núcleos, mientras que un Xeon Phi podía llegar a los 61 núcleos. Ahora bien, la complejidad del núcleo era bastante más sencilla que un núcleo de un Xeon estándar (por ejemplo, siendo un procesador en orden).
-
Tal y como se ha mencionado, había que traer aplicaciones HPC existentes en KNC/KNF. En términos de esfuerzo, esto implicaba que muchos usuarios se vieran obligados a migrar a estos nuevos tipos de sistemas. Ahora bien, en muchos casos esto no era posible. Por ejemplo, algunas de las aplicaciones más relevantes en entornos HPC podían tener millones de líneas de código que habría que adaptar a esta nueva arquitectura. Por lo tanto, evolucionar KNC/KNF hacia una arquitectura compatible con x86 estándar sería un aspecto importante a tener en cuenta.
-
El hecho de tener un modelo discreto implica que la aplicación tiene que mover los datos de cada huésped hacia el dispositivo cada vez (de forma similar a como el código ha de ser ejecutado). En muchos casos, esto puede añadir un coste extra que tiene un impacto en el rendimiento. Por otro lado, probablemente tener un modelo bootable que permitiera ejecutar directamente aplicaciones permitiría correr de forma más sencilla y natural aplicaciones OpenMP y MPI (las más frecuentemente empleadas en entornos HPC).
-
La cantidad de memoria proporcionada (16 GB) puede ser empleada para hacer cálculos para un determinado tipo de problemas. Ahora bien, para muchas aplicaciones HPC, el tamaño de problema empleado (denominado en inglés working set) acostumbra a ser mayor de 16 GB. Por lo tanto, desarrollar nuevos esquemas que permitieran tener una solución HPC con más memoria sería interesante.
-
Usar una interconexión de tipo anillo tiene la ventaja de que es una solución más sencilla de desarrollar. No obstante, puede mostrar dos limitaciones importantes:
-
Latencia variable. Dependiendo de “quién” con “quién” se establezca una comunicación, la latencia puede ser 16 veces más larga. Por ejemplo (asumiendo un ciclo para hablar con el siguiente elemento, un elemento X tarda 1 cycle en hablar con el X+1 y 16 para hablar con el elemento x+16.
-
Cuellos de botella. Por el hecho de que todos los elementos están conectados con un anillo bidireccional, se dan situaciones en que determinados componentes conectados a este pueden convertirse en vecinos molestos (en inglés, noisy neighbors). Por ejemplo, si un núcleo N está enviando muchas peticiones a memoria o a otro núcleo, el núcleo N+1 puede tener problemas para usar el anillo, pues siempre está ocupado por peticiones del núcleo N.
-
-
Tener muchos núcleos para obtener rendimiento incrementando el TLP es importante. Ahora bien, el hecho de que estén en orden los hace más complejos de programar. Por ejemplo, cuando se envían peticiones a memoria, el hilo en cuestión queda bloqueado hasta que los datos vuelven de memoria. En este caso, ir hacia arquitecturas de núcleo más complejas sería una manera de mejorar su programabilidad y rendimiento.
5.8.1.Red de interacción
5.8.2.Núcleos y modelos de coherencia
-
Procesa peticiones de los agentes de coherencia (que usan una estructura de directorios) para invalidar o cambiar el estado de líneas que tiene la L2.
-
Procesa peticiones de los núcleos para acceder a las líneas que potencialmente están en la L2 y para enviarle víctimas. Si las líneas pedidas por los núcleos no se encuentran en la L2, la lógica en cuestión genera una petición al directorio.
-
Mantiene la coherencia entre las L1 de los dos núcleos. Es decir, si estos están compartiendo datos, la lógica se encargará de que los datos sean coherentes entre los dos. Por ejemplo, invalidando el núcleo 1 si tiene una línea de memoria que pide el núcleo 2.