martes, 29 de diciembre de 2009

CoProcesadores para las GPU

Con la misma idea inicial que nacieron las tarjetas gráficas se llega a plantear añadir procesadores auxiliares que trabajen con nuestras GPU. Estos procesadores llevarán a cabo tareas más específicas y resolverlas por hardware en vez de dejar el peso en la programación. Actualmente las GPU están enfocadas a un uso más genérico como unidades de altos rendimientos de calculo en vez de la inicial idea de gráficos simplemente. Por ello se vuelve a pensar en coprocesadores más centrados en gráficos que las ayuden.
Como ejemplo de estos coprocesadores vamos a ver la Unidad de Procesamiento de Física o PPU: PHYSX. En particular, yo conocí la existencia de este coprocesador por noticias de varios videojuegos desarrollados con esa base (Batman: Arkham Asylum). Este coprocesador está diseñado por Nvidia y permite realizar calculos físicos de en entornos 3D de videojuegos. Este coprocesador hace aparición a partir de la serie 8 de tarjetas, además la compañía provee de un kit de desarrollo específico para el coprocesador.
A continuación una demo sobre líquidos y partículas representadas con el coprocesador:

Analizando análisis: Tom Hardware


Los análisis y comparativas de tarjetas gráficas son muy abundantes en los foros de videojuegos. Pero tal y como hemos visto en clase la mayoría de comparaciones son realizadas sobre medidas poco correctas, como el numero de teraflots o la memoria de cada tarjeta gráfica.
En clase estuvimos analizando este tipo de medidas y una de las páginas que vimos fue Tom´s Hardware. Así que quise informarme a través de esta página de análisis de GPUs actuales y no tan actuales. En esta página web encontré un un articulo bastante interesante (y creo que completo) sobre distintas tarjetas gráficas: Resumen del cuarto trimestre de 2009
En este artículo veíamos una comparativa de las gráficas de alto rendimiento del mercado. Está enfocado concretamente al rendimiento de juegos actuales pero no deja atrás el análisis de la tarjeta gráfica por parte de dos Bechmark (3dMark, por ejemplo)...eso si, ambos están enfocados a gráficos de juegos.
Cada análisis deja claro varios datos que son importantes a la hora de realizar el análisis de rendimiento, como la resolución con la que se va a trabajar. Estos detalles son clave en el fondo, ya que podemos ver si el rendimientos varía por las distintas configuraciones con las que trabajemos o por la tarjeta gráfica con que trabajemos en sí.
Algo que me ha llamado la antención de los análisis es que prueban muchos juegos, indican la configuración con la que los prueban y cosas por el estilo, pero no hablan del PC que se utiliza. El resto de componentes del PC también son importantes al evaluar el rendimiento de las tarjetas gráficas, pueden darse cuellos de botella en el Bus, por ejemplo. Imagino que los PCs utilizados serán de prácticamente iguales, pero cuando nosotros hagamos algún análisis de rendimiento deberíamos tenerlo en cuenta (fallo por mi parte en la evaluación que llevé a cabo en el Tema 1).
Por último resaltar que la medida que nos muestran de rendimiento es el número de frames por segundo (FPS). Como vimos en clase esta medida de rendimiento es bastante orientativa si tenemos en cuenta todos los demás aspectos del PC que estamos evaluando. Así que como conclusión, creo que la próxima vez que tenga que comprarme una tarjeta gráfica buscare información en esta página web.

Modelos de programación para el Cell

El Cell es un procesador muy potente y lo que es más importante, aunque lo tengamos en nuestras PS3, es un procesador de propósito general. Actualmente se está intentando sacar partido del Cell no solo en consola sino en investigaciones científicas. Por eso cuando debamos ponernos a programar en este tipo de máquina debemos pensar en que modelo de programación queremos seguir. A contiuación doy unos ejemplos.
  1. Programación Secuencial.- O también podemos llamarlo "como desaprovechar el multinucleo". Con este modelo (el de toda la vida) vamos realizando las tareas paso a paso y no indicamos a los distintos procesadores como deben repartirse las tareas, por lo tanto, no se la reparten.
  2. Modelo de programación de Dispositivos.- Este modelo consiste en tratar los distintos núcleos como dispositivos. Es parecido al modelo que se utiliza en los PC al programar aplicaciones en las que la CPU manda tareas a (por ejemplo) la tarjeta gráfica del PC. El procesador central (PPE) se dedicará a mandar tareas específicas a los SPE.
  3. Modelo de Streaming.- Básicamente, creamos un pipeline o cauce de ejecución con los distintos SPE, con esto conseguimos que tareas complejas se dividan en tareas simples y se puedan ejecutar en paralelo. Para hacernos una idea, es parecido a la filosofia de dividir las instrucciones del procesador en etapas simples y solapar la ejecución de las etapas en un mismo momento.
  4. Modelo de memoria compartida.- Este modelo se basa en que los SPE se encarguen de la misma tarea pero para muchos datos al mismo tiempo. Nuestra aplicación tendría un hilo de ejecución central por así decirlo, y en distintas partes del código tendríamos zonas en las que una misma tarea se reparte en distintos hilos para ejecutarse más rápidamente. Imaginaos un tabla muy grande que debemos procesar, pues llegada la zona en la que dividimos en hilos, cada dato de la tabla (o grupo de datos) se ejecuta por separado en distintos núcleos y se unifica el resultado después.
Estos solo son unos cuantos de los modelos que podemos utilizar. Evidentemente no son modelos exclusivos de la PS3, si os fijáis pueden ser utilizados para cualquier arquitectura multinucleo en la que queramos programar.

viernes, 25 de diciembre de 2009

Versus: Cell contra Xenon

Existen millones de foros con hilos de comparativas entre Xbox 360 y PS3, con la única base de como se ve un juego en una consola u otra, o de el número de núcleos o TFlops que pueden ejecutar. Aquí voy a intentar hacer una comparativa un poco distinto,vamos a comparar las arquitecturas y veremos cual nos parece "mejor".
En la entrada anterior me dediqué a analizar la CPU de la Xbox 360 haciendo referencia a mejoras de rendimiento. Ahora voy a analizar un poco el Cell y comparando paso a paso con el Xenon.
El Cell es un procesador multicore formado por 1 PPE y 8 SPE. El PPE es un procesador al estilo de los 3 que tiene el Xenon, Power PC de intel con 23 etapas por instrucción y a 3,2 Ghz. Al igual que los del Xenon no permiten ejecución fuera de orden pero si multithreading. La única gran diferencia que encontramos es que el PPE del Cell, además de incorporar cache de nivel 1 tiene su propia cache de 512 KB de nivel 2.


Los SPE son la gran diferencia de la CPU. Nos encontramos con 8 núcleos que trabajan a la misma frecuencia que el PPE y que tampoco permiten ejecución fuera de orden pero si multihilo. ¿Entonces en que lo diferenciamos? Pues en que los SPE, no tienen memoria cache de ningún tipo, utilizan almacenamiento local de 256 KB. Esto parece un desperdicio de procesador, pero la filosofía de la arquitectura se pueden aprovechar. Los SPE están conectados a un Bus de muy altas prestaciones llamado EIB que permite la comunicación entre ellos y además cada SPE puede acceder a los registros locales de otros SPE, intentan explotar que los SPE trabajen con el mayor paralelismo posible. Estos procesadores no son tan complejos como los del Xenon, pero son más y trabajan casi del mismo modo.
Resumiendo un poco las ideas, parece que el Cell es mejor, pero todo tiene un pero. Es cierto que el Cell es más complejo y puede llevar a cabo tareas con más paralelismo que el Xenon, pero tiene la misma pega pero con mayor complejidad, no resuelve problemas de eficiencia por hardware, dejando mucha responsabilidad a los programadores o compiladores. Esto en la Xbox 360 es notable, pero en la PS3 es mucho mayor el problema. Ninguna de las CPU están siendo programadas como es debido, ya que no es fácil pero en una destaca más que en otra, por eso se ven juegos en PS3 de la misma calidad que en Xbox 360, se realizan de forma genérica sin centrarse en la arquitectura y sin sacar el rendimiento debidamente.

PD: Casi todas las conclusiones son opinión propia.

miércoles, 16 de diciembre de 2009

Xenon Xbox 360, al detalle

Vamos a comenzar por dar un vistazo en general al Xenon. Según las especificaciones tiene tres núcleos PowerPC de 21 etapas de segmentación, cada núcleo permite hyperthreading y trabaja a 3.2 GHz. Dicho así suena muy impresionante, pero vamos a mirarlo más de cerca.
Tanta frecuencia de reloj parece un poco abrumadora, pero si tenemos en cuenta que en cada ciclo se ejecuta una etapa de una instrucción cualquiera, y que una instrucción se divide en 21 etapas, ya veis que la velocidad de ejecución por instrucción es menor (y mejor medida de rendimiento) que la frecuencia de reloj. Pero de cara al mercado es mucho mejor decir que la CPU corre a 3.2 GHz, cosas del marketing.
Ahora vamos a meternos en la manera de trabajar del Xenon. AL contrario que otras CPU de proposito general, la Xenon no puede trabajar con ejecución fuera de orden con las instrucciones, pero si tiene la ventaja del multithreading. Esto nos permitirá ejecutar por ejemplo en cada núcleo un par de hilos de ejecución y teniendo en cuenta sus 3 núcleos, en la teoría podríamos ejecutar 6 hilos al mismo tiempo. Esto nos da un rendimiento bastante bueno al fin y al cabo, pero la arquitectura tiene un pega, esta filosofía es un problema para el desarrollo de software eficiente en la consola.
Cambiemos de ámbito a analizar de la consola, la jerarquía de memoria y el acceso a ella es otro ámbito que merece la pena mencionar. La arquitectura tiene dos niveles de memoria cache, que nos da una mejora de rendimiento respecto a 1 solo nivel o el acceso a memoria principal directamente. Cada procesador tiene su propia cache de primer nivel de 64, dividida en dos (instrucciones/datos) para evitar fallos de acceso. En cambio el nivel 2 de memoria cache es compartida entre todos los procesadores, y la mayoría de veces utilizado únicamente como simple buffer de almacenamiento.
Toda esta arquitectura nos da un máquina con eficiente, centrada en el multithreading y parecida a las de propósito general, pero con mucha carga de eficiencia de rendimiento que deben solucionar los programadores.

lunes, 30 de noviembre de 2009

Explicación al detalle de las técnicas de gestión de E/S

Un ordenador no puede funcionar si no tiene datos para poder trabajar con ellos. Estos datos no se crean de la nada, sino que tienen que alguien tiene que ponerlos en el ordenador a través de un sistema de Entrada/Salida.
Los dispositivos de E/S (teclado, ratón,…) se comunican con la CPU a través del bus del sistema. Al no estar tan optimizada la E/S como el resto de sistemas, puede llevar a la bajada de rendimiento de nuestros equipos. Para solucionar esto, se han ideado técnicas de gestión con las que realizar las tareas de E/S sin que afecte al resto del sistema.

E/S Programada.- Es tan simple como que la CPU realiza un sondeo (en bucle) sobre si los controladores del dispositivo de E/S para ver su estado, y usarlos cuando sea preciso. Este sistema está anticuado, ya que la CPU estará la mayoría de veces en espera de los dispositivos de E/S.

E/S por Interrupciones.- En vez de ser la CPU la que espere al dispositivo, será el dispositivo el que interrumpa a la CPU para avisar de la finalización de las operaciones. Entonces la CPU puede resolver que dispositivo ha lanzado la interrupción, realizar las operaciones necesarias (rutina de manejo de interrupciones) y enviar la siguiente operación al dispositivo.
Esta técnica permite a la CPU estar trabajando en otras operaciones sin dedicarle tiempo al dispositivo. Este manejo de la E/S puede parecer un mecanismo bastante bueno, pero todo depende de si hay excesiva carga de E/S, porque si se da el caso la CPU puede dedicar demasiado tiempo al manejo de estas instrucciones y llegar de nuevo a la bajada de rendimiento.

E/S por DMA (Acceso Directo a Memoria).-
Tendremos un dispositivo auxiliar que controlará por sí mismo la escritura de E/S directamente en memoria, sin pasar por la CPU. La CPU sigue teniendo carga de trabajo, pero es mínima, solo se encarga de decirle a la DMA la fuente/destino de la transferencia de datos. Para poder llevar a cabo la transferencia de datos, la DMA “roba” un ciclo del bus el sistema para poder escribir en memoria. Una vez los datos estén en memoria la DMA avisa a la CPU que los datos están listos.
Esta forma de trabajar evita que la CPU tenga que estar cambiando de contextos de procesos cada vez que una operación de E/S de termine. En contra tenemos que el DMA y la CPU estarán compitiendo por el uso del bus y puede darse que la CPU trabaje a menor velocidad al final.

E/S por Procesador Dedicado.-
Hoy en día el peso de las operaciones de E/S se deja sobre un co-procesador dedicado exclusivamente a ello. La CPU solo se comunica con él para comunicarle sus necesidades de los dispositivos de E/S. El procesador de E/S ejecuta código propio para controlar la operación. Además, en la actualidad, se añade cierta cantidad de memoria RAM a los dispositivos, y las transferencias se realizan sobre esta memoria.

Comparativa: PCI‐Express vs. PCI y AGP

Poniéndonos en antecedentes podemos ver como los buses PCI y AGP “competían” en la misma época. Ambos estaban presentes en numerosas tarjetas gráficas y de prestaciones equiparables, aunque cada una trabajase de cierta manera. PCI-Express es la evolución del PCI y el bus actual de las tarjetas gráficas. Pasemos a ver las características de cada uno.

PCI.- El bus PCI tiene 32 bits de comunicaciones que trabajan a una frecuencia de 33 MHz, por lo tanto la tasa de transferencias teórica es de 133 Mbits/s. Velocidad de transferencia más que suficiente para cualquier tarjeta gráfica 2D.
Evidentemente no solo hay un tipo de PCI, dependiendo de los requisitos electrónicos se pueden dividir en tres tipos.
  1. PCI de 5 voltios.
  2. PCI de 3.3 voltios, más usadas en ordenadores portátiles.
  3. Universales, seleccionan el voltaje automáticamente y se utilizan tanto en sobremesas como en portátiles.
También existen distintas ranuras de acuerdo con los bits que se puedan transportar.
  • Ranuras de 32 bits: son las normales y más extendidas.
  • Ranuras de 64 bits: muy recientes, agregan 32 conectores más.
AGP.- Bus para conectar periféricos a la placa base del equipo. Los buses AGP trabajan a distintas frecuencias y voltajes, hay más diferencias entre ellas que en el caso de las PCI.
  1. AGP 1X, frecuencia de 66 MHz y tasa de transferencia de 264 MB/s con un voltaje de 3,3 V.
  2. AGP 2X, frecuencia de 133 MHz y tasa de transferencia de 528 MB/s con un voltaje de 3,3 V.
  3. AGP 4X, frecuencia de 266 MHz y tasa de transferencia de 1 GB/s con un voltaje de 3,3 o 1,5 V, para poder adaptarse al diseño de tarjetas gráficas.
  4. AGP 8X, frecuencia de 533 MHz y tasa de transferencia de 2 GB/s con un voltaje de 0,7 o 1,5 V.
PCI-Express.- Es mucho más veloz que los dos buses anteriores, convirtiéndose en el sustituto natural de los dos. Dependiendo del dispositivo existen PC-Express de distintas frecuencias de reloj. Para trabajar con dispositivos de sonido o de televisión se puede utilizar PCI-Express 1x (133Mhz). Pero en el caso de tarjetas gráficas se utiliza PCI-Express 16x de 2128Mhz. Existen más modelos (1x, 2x, 3x, 4x, 16x).
Se ha convertido en el sustituto de AGP por velocidad de transferencia y al ser la evolución del PCI se ha afianzado en el mercado.

viernes, 27 de noviembre de 2009

Análisis de Jerarquia de memoria: MacBook

Voy a centrarme en el análisis de la jerarquia memoria de un ordenador que hoy en dia esta de moda (no se puede definir de otra manera). El MacBook es un ordenador portatil de Mac con unas especificaciones muy concretas, no es tan buena máquina como diseño, al estilo de los productos Mac. Según he podido investigar la jerarquia de memoria del equipo queda de la siguiente manera:
  • Caché L1: el MacBook lleva un procesador Intel Core 2 Duo con dos niveles de cache. Cada core lleva un nivel L1 de 64 KB (32 de instrucciones/32 de datos).
  • Caché L2: Un nivel de cache L2 de 3 MB compartida por el par de nucleos que funciona a la velocidad del procesador. Los dos niveles de cache trabajan a la frecuencia de reloj del procesador, 2,26 GHz.
  • Bus de comunicación frontal: Conecta la CPU, memoria principal y el resto de componentes del equipo. Trabaja a 1.066 MHz.
  • Memoria Principal: Dos módulos SO-DIMM de memoria DDR3 de 1 GB cada uno, un total de 2 GB. Trabaja a 800 MHz (2 transferencias por ciclo).
  • Memoria secundaria: Disco duro SATA de 250 GB o 500 GB.

jueves, 26 de noviembre de 2009

Memorias DRAM de Tarjetas Gráficas y Consolas

Toda arquitectura (tanto gráfica como de propósito general) tiene una memoria principal. Al aparecer arquitecturas dedicadas a gráficos se provocó un avance, y una especialización de memorias dedicadas a gráficos. En este post daré un repaso leve a distintas memorias DRAM para tarjetas gŕaficas y comentaré los tipos de memoria de la actual generación de consolas.

Memorias DRAM en Tarjetas Gráficas
:
  • DRAM EDO.- Esta memoria era capaz de acceder introducir datos mientras los de salida aun no estan colodos en el BUS del sistema, tenían una especie de buffer. La máxima velocidad de lectura de la memoria EDO RAM es de 5-2-2-2 ciclos y es difícil crear memorias de este tipo que funcionen a velocidades de reloj superiores a 66Mhz.
  • VRAM.- Este memoria es exclusiva de vídeo. Esta memoria era muy similar a la EDO, la principal caraterística es que se podía acceder a memoria desde dos dispositivos a la vez, tenia un puerto dual, o leer y escribir al mismo tiempo.
  • WRAM.- No es más que una VRAM optimizada, trabaja del mismo modo, con puerto dual, pero tiene un tiempo de acceso más rápido y es más barato.
  • SGRAM.- Es un tipo de especialización de la memoria SDRAM (de ámbito general). Añade mejoras a la hora de escribir en un solo bit sin afectar a otros y escritura de linea entera de un mismo "color". Tiene un solo puerto de entrada y salida pero puede simular el doble puerto creando dos paginas de memoria
  • MDRAM.- Esta arquitectura define la memoria como un conjunto de bloques pequeños (32 KB) en paralelo conectados a un BUS. Esto conlleva poder trabajar con accesos a memoria en paralelo.
  • 3DRAM.- Es una memoria optimizada para 3D, ya que integra en la memoria una unida ALU para poder llevar a cabo operaciones (Z-Buffer, por ejemplo) en la misma memoria.
  • GDDR (1,2,3, 4, 5).- Son memorias basadas en la tecnología DDR (dos transferencias por ciclo, en bajada y subida) pero optimizadas para tarjetas gráficas. Los distintos tipos son sucesivas mejoras en rendimiento, velocidad y amplitud de ancho de banda, pero la arquitectura sigue siendo la misma. Las tarjetas gráficas de alta prestaciones actuales usan GDDR5 y las de baja GDDR3.
Después de ver este leve resumen, podemos observar como los avances en memoria se dan de manera paralela entre memoria para PC y para gráficos, siempre siendo la de gráficos optimizada.
Ahora veamos que tipos de memoria utilizan las consolas de la actual generación:
  • XBOX 360.- GDDR3 RAM a 700 Mhz, es una arquitectura convencional, no quiere decir que la tarjeta gráfica sea de baja gamma, simplemente no les hace falta más.
  • PS3.- Para sorpresa tiene dos módulos de memoria. Uno GDDR3 para la GPU (características similares a la XBOX) y otra XDR RAM, memoria de tipo Rambus RAM que se basa en una comunicación serie de alta velocidad y prestaciones.
  • Nintendo Wii.- GDDR3 normal para trabajar con gráficos y una ARAM (memoria de bajas prestaciones) dedicada exclusivamente al audio, así liberan la GDDR3 de datos de audio.

Organizaciones de Memoria Cache y su rendimiento

Uno de los problemas importantes a la hora de la velocidad de trabajo de un ordenador son los retardos por accesos a memoria. La CPU tiene que trabajar con datos, pero estar continuamente accediendo a la memoria principal es costoso en tiempo. Por ello en los ordenadores de hoy en día existe la Jerarquía de Memorias:Esta jerarquía nos ayuda a agilizar los accesos a memoria. Pero hay que tener en cuenta que el rendimiento que esta jerarquía (el caso que estudiamos el de la cache) depende totalmente de la organización de ellas.
Podemos pensar en la caché como una tabla dividida en filas, que serán las unidades básicas de almacenamiento. Cada vez que traemos información de le memoria principal a la caché, traemos como mínimo una línea, funcionando del mismo modo a la hora de escribir desde caché a memoria principal.
La idea principal que debemos tener en cuenta para organizar la cache, es como se va a comunicar la caché con la memoria principal. Es decir, como vamos a traducir las direcciones de la memoria principal en caché. Existen tres técnicas:

1) Caché completamente asociativa:
Este tipo de caché puede almacenar en cualquiera de sus filas cualquier posición de memoria principal. Esto quiere decir que no se realizan búsquedas para seleccionar en que parte de la caché se almacenará (en la primera línea vacía que tengamos) y que el acierto es muy alto. Pero por el contrario, el tiempo de acceso a la caché es muy alto, ya que al buscar cualquier dato nos encontramos con que puede estar en cualquier parte.

2) Caché de mapeado directo:
En este caso cada dirección de memoria principal tendrá una posición en caché concreta donde se debe almacenar. Esto nos da la ventaja de saber de antemano que al acceder a caché encontraremos la dirección que estamos buscando en esa linea, es decir, velocidad de acceso muy alta.
Pero por otro lado tenemos el inconveniente de que a una linea de caché corresponden varias posiciones de memoria principal, o lo que es lo mismo, que hay muchas posibilidades que cada vez que busquemos los datos en caché de cierta posición de memoria, encontremos datos referentes a otra posición, tendremos una alta tasa de fallos.

3) Caché asociativa por conjuntos:
Si ninguno de los métodos de organización anteriores son eficientes, podemos mezclarlos para dar una organización mixta. Esta es la idea de la "asociativa por conjuntos". La caché estará dividida por bloques o conjuntos con más de una linea, cada dirección de memoria principal corresponderá a un bloque y dentro del bloque se distribuirá de manera asociativa.
En este caso particular la eficiencia dependerá del tamaño del bloque que decidamos utilizar. Mientras mayor sea el tamaño de bloque la memoria parecerá más asociativa, y si es menor más de mapeado directo, cada una con sus ventajas e inconvenientes.

lunes, 9 de noviembre de 2009

Multithreading en Arquitecturas Gráficas

El Multithreading (o multihilo en español) es una forma de programar, y por consiguiente de estructurar el hardware del procesador para la compatibilidad, en la cual los hilos de ejecución comparten el mismo estado de memoria. Al separar las tareas en hilos de ejecución diferentes, el procesador puede llevar a cabo muchos más al mismo tiempo y, por lo tanto, aumentando la productividad. Evidentemente no es fácil de hacer, hay que tener en cuenta que se deben programar hilos teniendo en cuenta su tiempo de ejecución.
El Multithreading surgió en las CPU y hasta hace poco no se encontraban en las arquitecturas gráficas. A partir de 2008 surgen tarjetas gráficas con arquitecturas con varios núcleos, en los cuales se puede aprovechar el multithreading.
En clase hemos visto la serie 9 de las tarjetas gráficas de Nvidia. Las arquitecturas de esta serie de tarjetas gráficas incluyen una arquitectura multinúcleo. Pero no solo se trabaja de esta manera en las tarjetas gráficas, por ejemplo la tecnología Hybrid SLI de Nvidia. Esta tecnología en los portátiles trabaja con una tarjeta gráfica integrada en la placa base y otra no integrada, haciendo que las dos trabajen conjuntamente.
Un ejemplo más actual de este modo de trabajo lo tenemos en la nueva tecnología de Nvidia Fermi (vista en una entrada anterior del blog). Esta arquitectura tiene un controlador llamado GigaThread que se encarga exclusivamente de poder trabajar con el multithreading.

Predictores de salto multinivel y adaptativos

Los predictores de saltos son recursos hardware para reducir ciclos de paradas de la ejecución. Concretamente paradas provocadas por tener que evaluar una condición antes de decidir cual será la siguiente instrucción. Para poder crear predictores funcionales hay que estudiar el comportamiento de los programas. Hoy voy a analizar dos tipos de predictores en concreto:

Predictores de Salto Multinivel
Los predictores multinivel se caracterizan por utilizar información del salto para el que se realiza la predicción, junto a información del resto de saltos del programa.
Un ejemplo sencillo para entender esta clase de predictores es el paso del preditor 1-1. Su nombre viene de utilizar el comportamiento del último salto para seleccionar un predictor de 1 bit para el salto que estamos evaluando. El predictor que queda es el siguiente:
  1. El primer bit denomina la predicción si el último salto del programa no se había tomado.
  2. El segundo bit denomina la predicción en el caso contrario, si se ha tomado el último salto.
Los predictores multinivel se denominan M-N, es decir, utilizan el funcionamiento de los m últimos saltos tomados para escoger un predictor de n bits para el salto que se está evaluando.
Si tenemos la información de los saltos anteriores del programa podemos mejorar la tasa de aciertos de la predicción del salto actual. Pero tiene una pega grande, la gran complejidad del hardware que hace falta para tener encuentra la predicción de todos estos saltos.

Predictores Adaptativos
Estos predictores pueden seleccionar si trabajan con predictores que trabajen con información exclusivamente del salto con el que estamos trabajando o con información los n saltos anteriores (como los predictores multinivel).
Un ejemplo de predictor adaptativo trabajaría de la siguiente manera: Si las dos últimas predicciones de salto han fallado con un predictor que evalúa la información local, se cambia la siguiente predicción, para que se escoja teniendo en cuenta la información de otros saltos del código del programa.

sábado, 7 de noviembre de 2009

Análisis de una arquitectura de CPU: Intel Core i7

Al mismo hilo que la entrada anterior, vamos a analizar un poco la nueva arquitectura de CPU de Intel: Intel Core i7La principal característica de esta linea de CPU son sus 4 procesadores de 64 bits de tamaño de palabra. Se ha optimizado la comunicación entre los procesadores para acelerar la realización de tareas simultaneas.
Además, tal y como se puede apreciar en el esquema, cada procesador lleva consigo un controlador de memoria integrado. Este controlador ofrece mejoras en el ancho de banda y latencia para programas con uso intensivo de datos. Estas mejoras vienen en forma de 3 canales de comunicación con memoria principal DDR3. Esto, según hemos visto actualmente en clases, significa la posibilidad de trabajar con hasta tres módulos de memória principal DDR3 paralélamente.
No solo el acceso a la memoria principal se ha mejorado, la cache principal del procesador es de un tamaño de 8 MB, lo que ayuda bastante a la ejecución de programas.
Un último detalle que comentar son sus ocho subprocesos de procesamiento con la tecnología Hyper-Threading, con lo cual sus cuatro procesadores simularán ser 8 procesadores.

Análisis de una arquitecuta de GPU: Nvidia Fermi

Por seguir la evolución de las tarjetas Nvidia vistas en clase he preferido analizar la nueva arquitectura de Nvidia: Fermi.
Tal y como las series vistas en clase, el hardware está pensado para gestionar tres tipos de threads que se ejecutan en la GPU. En este caso se han ampliado la cantidad de chips como se hizo en el paso de la serie 6 a 7. Especialmente diseñado para ejecutar una enorme cantidad de tareas en paralelo.

-16 celdas de stream (Streaming Multiprocessor)
-32 cores en cada celda
-Cada celda contiene una memoria a modo de registros de 4 kb.
-2 niveles de chache. Nivel 1 de cache totalmente dedicada para cada celda de stream (1Mb) y una cache compartida por todas las celdas de nivel 2 (768Kb).
-Para la ejecución de threads se dispone de un controlador que los gestiona, el GigaThread.
-Además cada celda SM contiene procesadores especiales para calculo de operaciones complejas con números en coma flotante.

Como contrapunto, la única pega que se le puede sacar es la poca memoria por celda usada a modo de registros. Imagino que esto puede acarrear dificultades a la hora de la cantidad de operaciones que se ejecutan.

martes, 27 de octubre de 2009

Resolución de riesgos de Segmentación: MIPS

Antes de comenzar con las explicaciones detalladas de las técnicas de resolución, debería explicar brevemente en que consiste la Segmentación. Básicamente es una técnica que permite solapar la ejecución de instrucciones, dividiendolas en etapas. En las arquitecturas MIPS clásicas son:
  1. Búsqueda de la instrucción en memoria. IF
  2. Lectura de registros mientras se decodifica la instrucción. ID
  3. Ejecución de la operación o cálculo de una dirección. EX
  4. Acceso a un operando en memoria. MEM
  5. Escritura del resultado en memoria. WB
Estas etapas son ejecutadas por separado realizando la ejecución de las instrucciones del siguiente modo:

Pero la segmentación trae consigo problemas:
  1. Riesgos estructurales (Instrucciones que utilizan los mismos recursos a la vez)
  2. Riesgos de datos (Necesidad de datos que aun se están calculando)
  3. Riesgos de control (Problemas al controlar los saltos en un código)
Existen técnicas para resolver estos riesgos. A continuación voy a explicar las que se utilizan en los procesadores tipo MIPS clásicos:

ESTRUCTURALES. En este caso se ha decidido duplicar los recursos. Por ejemplo, en cierto código la etapa de IF de una operación se ejecuta al mismo tiempo que la MEM de otra (como en la imagen anterior). Esto crea un conflicto ya que ambas etapas acceden a memoria. En MIPS se ha separado la memoria de datos y de instrucciones, de esta manera se evitan todos estos conflictos.

DE DATOS. Supongamos en este caso que tenemos una instrucción add seguida de una instrucción sub:
add $s0, $t0, $t1
sub $t2, $s0, $t3
En este caso la segunda instrucción se verá obligada a esperar antes de la etapa EX hasta que la primera escriba en memoria. La arquitectura MIPS lo soluciona con cortocircuitos o anticipación. Esta técnica consiste en unir la ALU (Unidad Aritmético Lógica, en español) perteneciente a la ejecución de la etapa EX de la primera instrucción, con la entrada de datos de la etapa EX de la segunda instrucción, evitando así el acceso a memoria.

DE CONTROL. Cuando la instrucción a ejecutar se trata de un salto, no se sabe si la siguiente instrucción será la que se debe ejecutar. Esto trae muchos problemas de espera ya que en los códigos es muy común instrucciones de tipo if o while. Existen soluciones como bloquear la ejecución, predecir el salto o retardar la decisión. Esta última es la utilizada en los procesadores MIPS.
Su funcionamiento es sencillo, mientras se decide si el salto se debe tomar o no, el procesador pone como siguiente instrucción a ejecutar una que no dependa de la decisión del salto. Todo el proceso de que instrucción colocar es "invisible" para el programador, el procesador se encarga de ello de manera automática.

Como detalle bibliográfico, todas estas técnicas vienen especialmente bien explicadas en el libro Estructura y diseño de computadores de D.A. Patterson y J.L. Hennessy, Volumen 2. Me ha sido especialmente útil y los ejemplos sobre la segmentación comparada al proceso del lavado de ropa es muy fácil de ver.

lunes, 19 de octubre de 2009

RISC vs. CISC

Antes de meternos a comparar voy a explicar brevemente uno y otro tipo de arquitectura de CPU:
-CISC (complex instruction set computer): Como su propio nombre implica, son CPUs de una variedad muy amplia de instrucciones y que permiten operaciones muy complejas con registros, esto conlleva instrucciones de tamaño grande y que tardan varios ciclos de reloj en ejecutarse, pero a cambio da una gran potencia al microprocesador.
Uno de los contras (bajo mi punto de vista personal) es la dificultad de aplicar mejoras al rendimiento de la CPU como el paralelismo de instrucciones, es decir, cuesta mucho poder ejecutar varias instrucciones al mismo tiempo.
Por otro lado la arquitectura CISC ayuda al desarrollo software, ya que al tener un juego de instrucciones tan amplio y potente las aplicaciones son mas fáciles de desarrollar y los compiladores dejan mucha carga de trabajo a la CPU, no son tan complejos.

-RISC (
reduced instruction set computer): Son la filosofía contraria a los CISC, en ellos el conjunto de instrucciones es reducido y de tamaño fijo, por lo tanto toman menos tiempo en ejecutarse. Además dejan la carga del acceso a memoria sobre dos instrucciones.
El hecho de que las instrucciones sean fijas y de código de operaciones simples facilita la estructuración de las operaciones y que se pueda decodificar la operación mientras se accede a los registros de memoria. Todas las mejoras facilitan el uso de segmentación y paralelismo.
Las pegas de los procesadores RISC tienen mucho que ver con el software. Ofrecen un peor soporte para la programación en lenguajes de alto nivel, los compiladores son mas complejos y difíciles de crear.A parte, si un programa en CISC se podía escribir con 2 instrucciones, en RISC ocuparían muchas mas y por lo tanto el programa seria mas largo y tardaría mas en ejecutarse aunque las operaciones tardasen menos ciclos.

En conclusión final, cada uno tiene sus ventajas, pero creo que la elección de un tipo u otro de procesador al final viene por sopesar el coste y las aplicaciones que se utilizarán.

martes, 13 de octubre de 2009

Análisis de hardware: SPECviewperf 10.0

Tal y como se comentó en clase he llevado a cabo un test de SPECviewperf. A parte de intentar comprender los resultados que me da la aplicación, he decidido comparar los resultados de mi tarjeta gráfica algunos ordenadores que nos proporciona la facultad.
A continuación los resultados de mi PC, ATI Radeon X800 GTO de 256 MB:
Previamente había realizado ya las pruebas en un PC de la facultad y me llevé una grata sorpresa, ya que pensaba que mi tarjeta gráfica (comprada hace casi 5 años) no rendiría en comparación.
A continuación los resultados del PC de la facultad, nVIDIA Riva TNT2 64 MB:
Visto esto, además de informarme sobre que pone a prueba cada una de las aplicaciones, si tengo que realizar cualquier practica que necesite respuesta del PC utilizaré el mio propio. No es una queja, ni mucho menos, a los medios de la facultad, ya que solo he puesto a prueba un puesto normal de acceso a internet, me quedaría poder examinar un PC del laboratorio.
Por otro lado, buscando información sobre el benchmarks en cuestión, me he dado cuenta que es una herramienta más utilizada de lo que creía. Tanto en foros de juegos, del mundo 3D o de noticias tecnológicas sobre rendimientos del PC, se utiliza bastante esta herramienta para comparar hardware. Aunque a veces simplemente examinan bajo la regla de "mientras más grande mejor"

miércoles, 7 de octubre de 2009

Evolución de las consolas: Nintendo

Tenía pensado hacer un post sobre la evolución de los videojuegos, pero voy a centrarme en consolas, dado que la asignatura es más hardware que software. Concretamente voy a analizar la história de Nintendo en las consolas de sobremesa.

-NES (Nintendo Entertainment System): Lanzada en Japón en 1983 fue la consola mas exisota de su época, y con diferencia. La consola contaba con una CPU de 8 bits y una memoria RAM interna de 2 KB. Además ya incorporaba un procesador que se dedicaba exclusivamente a las imágenes, era capaz de mostrar 52 colores en pantalla y conseguir una resolución de 256x240 píxeles.

-Super Nintendo: 7 años después llegó al mercado la siguiente consola, en 1990, con una serie de mejoras muy vistosas. En este caso la CPU de 16 bits contaba con una ampliación de memoria muy relevante de 2 a 128 KB. Por otro lado el procesador de imágenes era capaz de mostrar 32,768 colores y llegar a una resolución de 512x448, que por otra parte rara vez utilizaban los juegos.

-Nintendo 64: Solo 6 años después hizo acto de presencia la siguiente generación de Nintendo. Esta consola no solo traía consigo un salto muy grande de hardware, CPU de 64 bits de arquitectura RISC y Procesador de Video (GPU) con, por ejemplo, anti-aliasing y corrección de perspectiva. Claramente era la primera consola de Nintendo centrada en el 3D y gracias a su I+D para llevarla a cabo, Sony pudo dar lugar a su famosa PlayStation.

-Game Cube: Otros 5 años mas tarde Nintendo lanzó su nuevo Hardware. Tanto el procesador gráfico como la memoria dedicada a los gráficos se aumentó bastante y el hardware de la consola en general fue bastante bueno en su momento, siendo de los mejores (si no el mejor) de su generación de consolas. A parte de estas mejoras gráficas, la Game Cube traia consigo la lecutara de disco en vez de cartucho como soporte de los videojuegos.

-Wii: Actual consola de Nintendo, vio la luz en 2006. En comparación con los avances de las anteriores generaciones Wii casi no llegó a "subir un escalón". Casi todo el hardware tiene muy poco avance en comparación a su predecesora, y eso se nota en la calidad visual de sus juegos. Pero aun siendo la consola con menos "potencia" gráfica, ha sido un superventa por su detección de movimiento y el buen marketing de la compañía al abrir el mundo de los videojuegos a un público mucho mas amplio.

martes, 6 de octubre de 2009

Historia y Evolución de APIs: OpenGL

A principios de los 90 las aplicaciones 3D no estabana a la orden del día, pero ya existia una competitividad en el mercado hardware. IBM y HP, entre otros, competian con Silicon Graphics Inc. en este mercado. SGI, por su parte, utilizaba una API llamada IrisGL que, aunque considerada mejor y más sencilla que las usadas por la competencia, perdía valor poco a poco frente a estas. Debido a esto SGI decidio abrir esta API de programación para que se adoptase como estándar, dando vida a OpenGL.
En 1995 Microsoft lanzó Direct3D que a partir de ese momento se convirtió en el competidor directo de OpenGL. En 1999 SGI tuvo que abandonar el proyecto por restricciones y poco apoyo indrustrial, pero hoy en día siguen desarrollando versiones:

-En 3Dlabs se desarrollo la version OpenGL 2.0, continuando con el desarrollo de la API, y creando el estandar GLSL, o lenguaje de sombreado de OpenGL
-En 2006 se publicó OpenGL 2.1, compatible con versiones anteriores, soporte de especificacion de matrices no cuadradas, Pixel buffer para acelerar el tráfico de imágenes y texturas sRGP
-Entre 2008 y 2009 se han dado a conocer las versiones 3.0, 3.1 y 3.2. Con aportes como revisiones del lenguaje GLSL, texturas, render buffers y Z-buffer en coma flotante 32-bits, Soporte de Geometría Shader.

Para más detalles se puede encontrar información muy interesante en la pagina oficial, en la serie de libros Rojo, Azul, Verde, Alpha y Naranja u otros igual de interesantes y en páginas como NEHE, donde tienen una colección de ejemplos básicos y no tan básicos para programar con OpenGL