UNIVERSIDAD DE EXTREMADURA
Escuela Politécnica
Ingeniería Informática
Proyecto Fin de Carrera
Desarrollo de algoritmos de análisis de
imágenes hiperespectrales en tarjetas gráficas
NVidia
Sergio Sánchez Martínez
Diciembre, 2008
Proyecto fin de carrera
-2-
Sergio Sánchez Martínez
Proyecto fin de carrera
-3-
Sergio Sánchez Martínez
UNIVERSIDAD DE EXTREMADURA
Escuela Politécnica
Ingeniería Informática
Proyecto Fin de Carrera
Desarrollo de algoritmos de análisis de
imágenes hiperespectrales en tarjetas gráficas
NVidia
CALIFICACIÓN: FECHA: Autor: Sergio Sánchez Martínez
Fdo.:
Directores: Antonio Plaza Miguel y
Fdo.:
Tribunal Calificador Presidente: Pablo Martínez Cobo Fdo.:
Secretario: David Valencia Corrales Fdo.:
Vocal: José Moreno del Pozo Fdo.:
Proyecto fin de carrera
-4-
Sergio Sánchez Martínez
Proyecto fin de carrera
-5-
Sergio Sánchez Martínez
Índice
1. Motivaciones y Objetivos ... 10 1.1. Motivaciones ... 10 1.2. Objetivos ... 12 2. Introducción ... 152.1. Concepto de imagen hiperespectral ... 15
2.2. Sensores hiperespectrales considerados ... 18
2.3. Técnicas de análisis hiperespectral y necesidad de paralelismo ... 21
3. Tarjetas gráficas programables (GPUs) ... 25
3.1. Las GPUs como un dispositivo de computación de datos en paralelo. ... 25
3.2. CUDA: Una Nueva Arquitectura para el Cálculo en la GPU... 30
3.3. Procesamiento ... 35
3.4. Implementación hardware y modelo de ejecución ... 38
4. Métodos ... 45
4.1. Píxel Purity Index (PPI) ... 45
4.2. Versión Kernel del algoritmo Píxel Purity Index (KPPI) ... 49
4.3. AMEE (Automated Morphological Endmember Extraction) ... 52
5. Procesamiento paralelo en GPU ... 62
5.1. PPI ... 62
5.2. Kernel PPI (KPPI) ... 63
5.3. AMEE ... 70
6. Resultados ... 73
6.1. PPI ... 87
6.2. Kernel PPI (KPPI) ... 100
6.3. AMEE CUDA ... 113
6.4. Análisis cualitativo... 121
6.5. Discusión y comparativa de algoritmos ... 128
7. Conclusiones y líneas futuras ... 134
8. Bibliografía ... 137
9. Apéndice ... 140
9.1. Programación con CUDA ... 140
Proyecto fin de carrera
-6-
Sergio Sánchez Martínez
Índice de Figuras
Figura 2.1 Concepto de imagen hiperespectral. ... 16
Figura 2.2 Adquisición de una imagen hiperespectral por el sensor AVIRIS ... 17
Figura 2.3 Tipos de píxeles en imágenes hiperespectrales ... 18
Figura 2.4 Evolución de la relación SNR del sensor AVIRIS de NASA ... 20
Figura 2.5 Interpretación gráfica del modelo lineal de mezcla ... 22
Figura 3. 1 Operaciones en coma flotante por segundo para CPU y GPU. ... 25
Figura 3. 2 Pipeline clásico de procesamiento para una GPU. ... 27
Figura 3. 3 La GPU proporciona más transistores para el procesamiento de datos. ... 29
Figura 3. 4 Pipeline clásico frente a pipeline unificado. ... 32
Figura 3. 5 Pila software de CUDA ... 33
Figura 3. 6 Operaciones de memoria gather (dispersión) y scatter (reunión) ... 34
Figura 3. 7 La memoria compartida proporciona los datos más cerca de las ALUs. ... 34
Figura 3. 8 El host emite al device una sucesión de invocaciones de kernels. Cada kernel se ejecuta como un grupo de hilos organizados como un grid de bloques de hilos. ... 37
Figura 3. 9 Un hilo tiene acceso a la DRAM del device y a la memoria on-chip a través de un conjunto de espacios de memoria para varios propósitos. ... 38
Figura 3. 10 Arquitectura de la GPU GeForce 8800 GTX de NVidia. ... 39
Figura 3. 11 Conjunto de multiprocesadores SIMD con memoria compartida on-chip .... 40
Figura 4. 1 Funcionamiento del algoritmo PPI ... 49
Figura 4. 2 Cálculo del píxel más puro espectralmente (a) y del más mezclado (b) en una ventana K usando la distancia acumulativa D... 54
Figura 4. 3 Diagrama de bloques que resume el funcionamiento del método AMEE. .... 56
Figura 4. 4 Recorridos más habituales de los píxeles de la imagen original. ... 59
Figura 4. 5 Selección del píxel máximo en una vecindad mediante un proceso de votación. 60 Figura 5. 1 Calculo de las ventanas ... 64
Figura 5. 2 Incrementos parciales: estado inicial ... 68
Figura 5. 3 Incrementos parciales: primera iteración ... 69
Figura 5. 4 Incrementos parciales: estado final ... 69
Figura 6. 1 Regiones y asignación de abundancias para la primera imagen sintética. .... 74
Figura 6. 2 Mapas de abundancia empleados en la generación de la primera imagen sintética. a) Mapa de abundancia para el endmember suelo. b) Mapa de abundancia para el endmember vegetación. ... 75 Figura 6. 3 Segunda imagen sintética. a) Distribución en la imagen de los cinco píxeles puros (endmembers), denotados como r1, r2, r3, r4 y r5. b-f) Mapas de abundancia
Proyecto fin de carrera
-7-
Sergio Sánchez Martínez
empleados en la generación de la segunda imagen sintética. ... 76
Figura 6. 4 Ubicación de la imagen real AVIRIS Cuprite sobre una fotografía aérea de la región minera Cuprite, Nevada, Estados Unidos. ... 77
Figura 6. 5 Precisión estricta PPI simple: Imagen sintética 1 ... 79
Figura 6. 6 Precisión estricta PPI: Imagen sintética 2 ... 80
Figura 6. 7 Precisión ponderada PPI: Imagen sintética 1 ... 81
Figura 6. 8 Precisión KPPI y AMEE... 82
Figura 6. 9 Precisión estricta KPPI y AMEE: Imagen sintética 1 ... 84
Figura 6. 10 Precisión estricta KPPI y AMEE: Imagen sintética 2 ... 85
Figura 6. 11 Precisión ponderada KPPI y AMEE: Imagen sintética 1 ... 86
Figura 6. 12 Resultados visuales para PPI en sus versiones C++ y CUDA para 1000 iteraciones usando la imagen sintética 1 ... 88
Figura 6. 13 Resultados visuales para PPI global en sus versiones C++ y CUDA para 10000 iteraciones usando la imagen sintética 1 ... 90
Figura 6. 14 Resultados visuales para PPI global en sus versiones C++ y CUDA para 1000 iteraciones usando la imagen sintética 2 ... 92
Figura 6. 15 Resultados visuales para PPI global en sus versiones C++ y CUDA para 10000 iteraciones usando la imagen sintética 2 ... 93
Figura 6. 16 Resultados de PPI para las versiones C++ y ENVI sin umbralizar y en niveles de gris. ... 95
Figura 6. 17 Resultados de PPI para las versiones CUDA y ENVI sin umbralizar y en niveles de gris. 97 Figura 6. 18 Resultados en blanco y negro de PPI para las versiones C++ y ENVI estando la versión C++ umbralizada a un valor de 2 ... 98
Figura 6. 19 Resultados en blanco y negro para las versiones CUDA y ENVI ... 99
Figura 6. 20 Precisiones obtenidas por el algoritmo KPPI en sus versiones C++ y CUDA para la imagen sintética 1. ... 110
Figura 6. 21 Precisiones obtenidas por el algoritmo KPPI en sus versiones C++ y CUDA para la imagen sintética 2. ... 111
Figura 6. 22 Gráfica de tiempos y speedup para el algoritmo KPPI con la imagen sintética 1. 112 Figura 6. 23 Gráfica de tiempos y speedup para el algoritmo KPPI con la imagen sintética 2. 112 Figura 6. 24 Precisiones obtenidas por el algoritmo AMEE para la imagen sintética 1... 119
Figura 6. 25 Precisiones obtenidas por el algoritmo AMEE para la imagen sintética 2... 120
Figura 6. 26 Gráfica de tiempos y speedup para el algoritmo AMEE. ... 120
Figura 6. 27 Ventanas de KPPI, 10000 iteraciones, imagen sintética 1 ... 122
Figura 6. 28 Ventanas de KPPI, 10000 iteraciones, imagen sintética 2 ... 123
Figura 6. 29 Ventanas AMEE, imagen sintética 1 ... 125
Figura 6. 30 Ventanas AMEE, imagen sintética 2 ... 127
Figura 6. 31 Grafica comparativa de los tiempos empleados por los algoritmos KPPI y AMEE para las dos imágenes. ... 130 Figura 6. 32 Gráfica comparativa de las precisiones conseguidas por los algoritmos KPPI y
Proyecto fin de carrera
-8-
Sergio Sánchez Martínez
AMEE para la imagen sintética 1. ... 132 Figura 6. 33 Gráfica comparativa de las precisiones conseguidas por los algoritmos KPPI y AMEE para la imagen sintética 2. ... 132
Figura 9. 1 Ejemplo de incremento de un array a de N elementos por un escalar b .... 143 Figura 9. 2 Ejemplo de programa CPU y CUDA ... 144
Índice de Tablas
Tabla 3. 1 Lecturas y escrituras en los diferentes tipos de memorias ... 37 Tabla 3. 2 Características técnicas de la GPU GeForce 8800 GTX de NVidia. ... 39 Tabla 3. 3 Muestra el número de multiprocesadores y la capacidad de cómputo de las diferentes GPUs de nVidia ... 42
Tabla 6. 1 Resultados para PPI global en sus versiones C++ y CUDA para 1000 iteraciones usando la imagen sintética 1 ... 87 Tabla 6. 2 Resultados para PPI global en sus versiones C++ y CUDA para 10000 iteraciones usando la imagen sintética 1 ... 89 Tabla 6. 3 Resultados para PPI global en sus versiones C++ y CUDA para 1000 iteraciones usando la imagen sintética 2 ... 91 Tabla 6. 4 Resultados para PPI global en sus versiones C++ y CUDA para 10000 iteraciones usando la imagen sintética 2 ... 92 Tabla 6. 5 Medidas tomadas y resultados visuales del algoritmo PPI en sus versiones C++, CUDA y ENVI para 1000 iteraciones haciendo uso de la imagen real Cuprite. ... 94 Tabla 6. 6 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 5 x 5 píxeles en la imagen sintética 1. ... 101 Tabla 6. 7 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 9 x 9 píxeles en la imagen sintética 1. ... 102 Tabla 6. 8 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 15 x 15 píxeles en la imagen sintética 1. ... 102 Tabla 6. 9 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 25 x 25 píxeles en la imagen sintética 1. ... 103 Tabla 6. 10 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 51 x 51 píxeles en la imagen sintética 1. ... 104 Tabla 6. 11 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 5 x 5 píxeles en la imagen sintética 2. ... 105 Tabla 6. 12 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 9 x 9 píxeles en la imagen sintética 2. ... 106 Tabla 6. 13 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 15 x 15 píxeles en la imagen sintética 2. ... 107 Tabla 6. 14 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA
Proyecto fin de carrera
-9-
Sergio Sánchez Martínez
para un tamaño de ventana de 25 x 25 píxeles en la imagen sintética 2. ... 108 Tabla 6. 15 Resultados obtenidos por el algoritmo KPPI en las dos versiones C++ y CUDA para un tamaño de ventana de 51 x 51 píxeles en la imagen sintética 2. ... 108 Tabla 6. 16 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 5 x 5 píxeles en la imagen sintética 1. ... 114 Tabla 6. 17 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 7 x 7 píxeles en la imagen sintética 1. ... 114 Tabla 6. 18 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 9 x 9 píxeles en la imagen sintética 1. ... 115 Tabla 6. 19 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 15 x 15 píxeles en la imagen sintética 1. ... 115 Tabla 6. 20 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 25 x 25 píxeles en la imagen sintética 1. ... 116 Tabla 6. 21 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 5 x 5 píxeles en la imagen sintética 2. ... 116 Tabla 6. 22 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 7 x 7 píxeles en la imagen sintética 2. ... 117 Tabla 6. 23 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 9 x 9 píxeles en la imagen sintética 2. ... 117 Tabla 6. 24 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 15 x 15 píxeles en la imagen sintética 2. ... 118 Tabla 6. 25 Resultados obtenidos por el algoritmo AMEE en su versión CUDA para un tamaño de ventana de 25 x 25 píxeles en la imagen sintética 2. ... 118
Proyecto fin de carrera
-10-
Sergio Sánchez Martínez
1. Motivaciones y Objetivos
1.1. Motivaciones
El presente trabajo se ha desarrollado dentro de las líneas de investigación actuales del Grupo de Redes Neuronales y Procesamiento de Señal (GRNPS) de la Universidad de Extremadura, y consiste en la implementación eficiente de algoritmos para extracción de referencias espectrales puras o endmembers en imágenes hiperespectrales haciendo uso de GPUs para acelerar los cómputos relativos a la extracción de endmembers. En concreto los algoritmos implementados son tres: Píxel Purity Index (PPI), una nueva versión del algoritmo Píxel Purity Index que utiliza una ventana deslizante para incorporar información espacial, y el algoritmo AMEE (Automatic Morphological Endmember Extraction), prestando más atención a estos dos últimos. Las aplicaciones potenciales de dichos algoritmos son múltiples, destacando aplicaciones de detección de minerales, aplicaciones militares tales como detección de material armamentístico camuflado, anomalías, identificación de agentes contaminantes en aguas y atmósfera, etc.
Conviene destacar los algoritmos de análisis hiperespectral generalmente necesitan grandes cantidades de tiempo a la hora de proporcionar resultados, debido a la complejidad computacional de los mismos (en el caso de PPI o AMEE, los algoritmos deben ejecutar un gran número de iteraciones) y también debido al gran tamaño de las imágenes a procesar, lo cual requiere que la transferencia de datos entre el procesador y el dispositivo hardware especializado utilizado como coprocesador deba optimizarse. Al requerir tantas iteraciones, y tener dentro de estas operaciones no triviales, los algoritmos de análisis hiperespectral generalmente se traducen en un consumo de CPU elevado, por lo que la utilización de arquitecturas especializadas como coprocesadores puede resultar una alternativa altamente interesante.
Hasta la fecha, las técnicas tradicionales en la literatura para abordar este problema han optado por soluciones basadas en el uso de clusters y sistemas multiprocesador. La computación cluster, a pesar de su adaptabilidad al problema del tratamiento de datos hiperspectrales (especialmente, cuando dichos datos se encuentran almacenados en un repositorio de datos en tierra), presenta problemas en
Proyecto fin de carrera
-11-
Sergio Sánchez Martínez
cuanto al procesamiento de los datos en tiempo real dado el alto coste y elevados requerimientos en cuanto a espacio, peso y consumo (denominado payload en misiones de observación remota de la tierra). Por otra parte, la instalación de un cluster suele llevar asociada la disponibilidad de un número elevado de ordenadores interconectados entre sí para que compartan el procesamiento de datos a través de sus procesadores, lo cual hace incrementar la velocidad de ejecución y procesamiento de las aplicaciones; sin embargo, cada nodo (u ordenador) lleva ligado un precio y una serie de requerimientos en cuanto a espacio y consumo que alejan esta aproximación de las características requeridas en cuanto a payload en misiones reales de observación remota de la tierra.
Para solucionar estos problemas relativos a coste, consumo y peso, y además ofrecer además mejoras sustanciales en cuanto al tiempo de procesamiento, en el presente PFC proponemos una alternativa basada en un nuevo modelo de tratamiento de imágenes hiperespectrales basado en la utilización de GPUs. Conviene destacar que, con una sola GPU, pueden llegar a obtenerse mejoras notables a la hora de procesar cálculos de tipo científico, como es el caso de los algoritmos de tratamiento de imágenes hiperespectrales, a un coste razonable (no más de 500 euros) y además ocupando un espacio mínimo. No obstante, no todas las tarjetas GPU disponibles en el mercado se ajustan a nuestros requerimientos. Por ello si aplicamos los algoritmos propuestos a través de tarjetas convencionales o de gama baja, veremos que los resultados no sufren ningún tipo de mejoría; es más, podemos llegar a obtener peores resultados. Finalmente, indicar que en este proyecto se ha intentado ir un poco más allá, y para trabajar de forma totalmente innovadora se ha utilizado la arquitectura CUDA incorporada en las tarjetas gráficas de NVIDIA de las series 8 (ó superiores), Quadro y Tesla, siendo algunas de las tarjetas de la primera gama las que han sido objeto de estudio en este PFC.
Para la realización de este trabajo se ha utilizado una maquina con un procesador Intel Core 2 Quad 6600 una GPU NVidia GeForce 8800 GTX y el sistema operativo Windows XP. Por otra parte otra de las actividades desarrolladas en el presente trabajo consiste en la realización de un estudio cuantitativo y comparativo de los algoritmos implementados tanto en C++ para su ejecución en la CPU como en CUDA para su ejecución en la GPU así como un análisis de la
Proyecto fin de carrera
-12-
Sergio Sánchez Martínez
precisión de los resultados obtenidos.
1.2. Objetivos
Este trabajo pretende desarrollar sobre una GPU la implementación de tres algoritmos para la extracción de endmembers en imágenes hiperespectrales y establecer un estudio cualitativo y comparativo de los resultados obtenidos tras la ejecución de ambos. Concretamente los algoritmos son: Píxel Purity Index (PPI) en su versión simple y en su versión kernel (KPPI) y Automatic Morphological Endmember Extraction (AMEE).
La consecución del objetivo general anteriormente mencionado se lleva a cabo en la presente memoria abordando una serie de objetivos específicos, los cuales se enumeran a continuación:
• Establecer un estudio sobre la utilidad y el funcionamiento del algoritmo PPI en sus dos versiones y del algoritmo AMEE para extraer el grado de paralelismo inherente que presenta y utilizarlo para su implementación.
• Realizar un estudio sobre el lenguaje de programación CUDA para poder implementar los algoritmos.
• Implementar los algoritmos para su ejecución en la GPU y optimizar el tiempo de ejecución para el algoritmo KPPI y para el algoritmo AMEE.
• Implementar una serie de aplicaciones que nos permitan conocer la precisión que se ha logrado en la ejecución de los algoritmos para dos imágenes sintéticas de las cuales se conocen previamente sus características.
• Realizar un estudio comparativo sobre los resultados obtenidos.
Teniendo presentes los anteriores objetivos concretos, procedemos a describir la organización del resto de esta memoria, estructurada en una serie de capítulos cuyos contenidos se describen a continuación:
2) Introducción. En este capítulo introductorio se describen los conceptos fundamentales relacionados con análisis hiperespectral y
Proyecto fin de carrera
-13-
Sergio Sánchez Martínez
procesamiento de datos, enfatizando la necesidad de técnicas de procesamiento paralelo en este campo y proponiendo la utilización de las GPUs como procesador paralelo para este tipo de técnicas.
3) GPU. Este capítulo está dedicado a la GPU, hablaremos de cómo han ido evolucionando las GPUs programables, de los recursos que ofrecen y su capacidad de computo. Introduciremos una serie de conceptos para lograr entender cómo se lleva a cabo el procesamiento en una GPU mediante CUDA. Este capítulo también describe el hardware de la tarjeta 8800 GTX (G80) con la que se ha realizado el proyecto. 4) Métodos. Este capítulo describe y muestra la utilidad de los
algoritmos implementados (PPI, incluyendo su versión kernel, y AMEE) para el análisis hiperespectral así como su funcionamiento y filosofía.
5) Procesamiento paralelo en GPU. En este capítulo se muestra como se lleva a cabo el procesamiento paralelo en la GPU para el caso que nos ocupa, es decir para la ejecución del algoritmo KPPI y AMEE, centrándonos en cada una de las fases del algoritmo por separado. 6) Resultados. En este capítulo se describen las imágenes que se han
utilizado para probas los algoritmos, se muestran las diferentes formas de calcular la precisión para cada algoritmo, se muestran los resultados conseguidos y finalmente se comparan.
7) Conclusiones y líneas futuras. Este capítulo está dedicado a resumir las principales aportaciones realizadas por la presente memoria y a mostrar las conclusiones derivadas. Además, el capítulo sugiere un conjunto de líneas de trabajo que pueden ser abordadas en futuros trabajos. La memoria concluye con una serie de referencias bibliográficas utilizadas en el estudio.
8) Apéndice. En este capítulo se expone una guía de programación básica de CUDA y se muestra el código de los algoritmos implementados tanto en C++ como en CUDA. También se muestra el código de los algoritmos utilizados para calcular la precisión de los
Proyecto fin de carrera
-14-
Sergio Sánchez Martínez
Proyecto fin de carrera
-15-
Sergio Sánchez Martínez
2. Introducción
El presente capítulo se organiza de la siguiente forma. En primer lugar, describimos el concepto de imagen hiperespectral, detallando las particularidades y características propias de este tipo de imágenes de alta dimensionalidad. A continuación, describimos algunas características genéricas de los sensores de adquisición de este tipo de datos, haciendo énfasis en los sensores utilizados en el presente trabajo. Seguidamente, se muestra una visión general de las técnicas de desmezclado disponibles en la actualidad, con particular énfasis en el modelo lineal de mezcla, utilizado en el presente trabajo para abordar el problema de la caracterización sub-píxel de una imagen hiperespectral a partir de la identificación de los píxels espectralmente más puros en la misma. El capítulo concluye destacando la necesidad de de paralelismo en este campo y mostrando el papel de las GPU para su tratamiento.
2.1. Concepto de imagen hiperespectral
El asentamiento de la tecnología hiperespectral en aplicaciones de observación remota de la tierra ha dado como resultado el desarrollo de instrumentos de medida de muy elevada resolución en los dominios espacial y espectral. Los sensores hiperespectrales adquieren imágenes digitales en una gran cantidad de canales espectrales muy cercanos entre sí, obteniendo, para cada porción de la escena o píxel, una firma espectral característica de cada material.
El resultado de la toma de datos por parte de un sensor hiperespectral sobre una determinada escena puede ser representado en forma de cubo de datos, con dos dimensiones para representar la ubicación espacial de un píxel, y una tercera dimensión que representa la singularidad espectral de cada píxel en diferentes longitudes de onda [1]. La Figura 2.1 muestra la estructura de una imagen hiperespectral donde el eje X es el indicador de las líneas, el eje Y es el indicador de las muestras y el eje Z es el número de bandas, es decir, la longitud de onda de esa banda (canal).
Proyecto fin de carrera
-16-
Sergio Sánchez Martínez
Figura 2.1 Concepto de imagen hiperespectral.
Como puede apreciarse en la Figura 2.1, el resultado de la toma de datos por parte de un sensor hiperespectral sobre una determinada escena puede ser representado en forma de cubo de datos, con dos dimensiones para representar la ubicación espacial de un píxel, y una tercera dimensión que representa la singularidad espectral de cada píxel en diferentes longitudes de onda. En concreto, la capacidad de observación de los sensores denominados hiperespectrales permite la obtención de una firma espectral detallada para cada píxel de la imagen, dada por los valores de reflectancia adquiridos por el sensor en diferentes longitudes de onda, lo cual permite una caracterización muy precisa de la superficie de nuestro planeta. Como ejemplo ilustrativo, la Figura 2.2 muestra el procedimiento de análisis hiperespectral mediante un sencillo diagrama, en el que se ha considerado como ejemplo el sensor AVIRIS (Airborne Visible Infra-Red Imaging Spectrometer), desarrollado por NASA/Jet Propulsión Laboratory, el cual cubre el rango de longitudes de onda entre 0.4 y 2.5 µm utilizando 224 canales y resolución espectral de aproximadamente 10 nm. Líneas M u e st ra s Ban das 1 -4 Pixel en posición (x,y) ND en banda 1 ND en banda 2 ND en banda 3 ND en banda 4
Proyecto fin de carrera
-17-
Sergio Sánchez Martínez
Figura 2.2 Adquisición de una imagen hiperespectral por el sensor AVIRIS
Como puede apreciarse en la Figura 2.2, la capacidad de observación de este sensor permite la obtención de una firma espectral detallada para cada píxel de la imagen, dada por los valores de reflectancia adquiridos por el sensor en diferentes longitudes de onda, lo cual permite una caracterización muy precisa de la superficie de nuestro planeta. Conviene destacar que, en este tipo de imágenes, es habitual la existencia de mezclas a nivel de subpíxel, por lo que a grandes rasgos podemos encontrar dos tipos de píxeles en estas imágenes: píxel puros y píxel mezcla [2]. Se puede definir un píxel mezcla como aquel en el que cohabitan diferentes materiales. Este tipo de píxel son los que constituyen la mayor parte de la imagen hiperespectral, en parte, debido a que este fenómeno es independiente de la escala considerada ya que tiene lugar incluso a niveles microscópicos [3]. La Figura 2.3 muestra un ejemplo del proceso de adquisición de píxeles puros (a nivel macroscópico) y mezcla en imágenes hiperespectrales. Longitud de onda (µm) R ef le ct an ci a Sensor hiperespectral Imagen hiperespectral Pixel hiperespectral Firma espectral 0.4 2.5 224 bandas
Proyecto fin de carrera
-18-
Sergio Sánchez Martínez
Figura 2.3 Tipos de píxeles en imágenes hiperespectrales
El desarrollo tecnológico introducido por la incorporación de sensores hiperespectrales en plataformas de observación remota de la tierra de última generación ha sido particularmente notable durante los últimos años. En este sentido, conviene destacar que dos de las principales plataformas de tipo satélite que se encuentran en funcionamiento en la actualidad: Earth Observing-1 de NASA (http://eo1.gsfc.nasa.gov) y ENVISAT de la Agencia Espacial Europea (http://envisat.esa.int), llevan incorporados sensores de este tipo, permitiendo así la posibilidad de obtener imágenes hiperespectrales de la práctica totalidad del planeta de manera casi continua. A pesar de la gran evolución en los instrumentos de observación remota de la tierra, la evolución en las técnicas de análisis de los datos proporcionados por dichos sensores no ha sido tan notoria. En particular, la obtención de técnicas de análisis hiperespectral avanzadas, capaces de aprovechar totalmente la gran cantidad de información espacial y espectral presente en imágenes hiperespectrales, constituye un objetivo de gran interés para la comunidad científica. A continuación, describimos en detalle las características del sensor hiperespectral utilizado en el presente estudio.
2.2. Sensores hiperespectrales considerados
Pixel puro (agua) Pixel mezcla (suelo + rocas) Pixel mezcla (vegetación + suelo) Pixel puro (agua) Pixel mezcla (suelo + rocas) Pixel mezcla (vegetación + suelo) 0 1000 2000 3000 4000 5000 300 600900 1200 1500 1800 2100 2400 Long. onda (nm) R e fl e c ta n c ia 0 1000 2000 3000 4000 5000 300 600900 1200 1500 1800 2100 2400 Long. onda (nm) R e fl e c ta n c ia 0 1000 2000 3000 4000 300 600900 1200 1500 1800 2100 2400 Long. onda (nm) R e fl e c ta n c ia 0 1000 2000 3000 4000 300 600900 1200 1500 1800 2100 2400 Long. onda (nm) R e fl e c ta n c ia 0 1000 2000 3000 4000 300 600 900 1200 1500 1800 2100 2400 Long. onda (nm) R e fl e c ta n c ia 0 1000 2000 3000 4000 300 600 900 1200 1500 1800 2100 2400 Long. onda (nm) R e fl e c ta n c ia
Proyecto fin de carrera
-19-
Sergio Sánchez Martínez
En la actualidad, existe una amplia gama de sensores hiperespectrales de observación remota de la tierra. Dichos sensores pueden clasificarse según el modo en que son transportados (plataforma de transporte) en el momento de la toma de datos [4-6]. La mayor parte de los sensores hiperespectrales actuales son aerotransportados (siendo el ejemplo más claro de este tipo de instrumentos el sensor AVIRIS, considerado en el presente trabajo).
AVIRIS es un sensor hiperespectral aerotransportado con capacidades analíticas en las zonas visible e infrarroja del espectro [8-10]. Este sensor está en funcionamiento desde 1987. Fue el primer sistema de adquisición de imágenes capaz de obtener información en una gran cantidad de bandas espectrales estrechas y casi contiguas. AVIRIS es un instrumento único en el mundo de la teledetección, pues permite obtener información espectral en 224 canales espectrales contiguos, cubriendo un rango de longitudes de onda entre 0.4 y 2.5 m, siendo el ancho entre las bandas muy pequeño, aproximadamente 0.01 m.
En 1989, AVIRIS se convirtió en un instrumento aerotransportado. Desde ese momento, se realizan varias campañas de vuelo cada año para tomar datos mediante AVIRIS. El sensor ha realizado tomas de datos en Estados Unidos, Canadá y Europa, utilizando para ello dos plataformas:
• Un avión ER-2 perteneciente a NASA/Jet Propulsion Laboratory. El ER-2 puede volar a un máximo de 20 km sobre el nivel del mar, a una velocidad máxima de aproximadamente 730 km/h.
• Un avión denominado Twin Otter, capaz de volar a un máximo de 4 km sobre el nivel del mar, a velocidades de 130 km/h.
Algunas de las características más relevantes en cuanto al diseño interno del sensor AVIRIS son las siguientes:
• El sensor utiliza un explorador de barrido que permite obtener un total de 614 píxeles por cada oscilación.
Proyecto fin de carrera
-20-
Sergio Sánchez Martínez
EFOS- A, compuesto por un array de 32 detectores lineales.
• La cobertura en el infrarrojo es realizada por los espectrómetros EFOS-B, EFOS-C y EFOS-D, compuestos todos ellos por arrays de 64 detectores lineales.
• La señal medida por cada detector se amplifica y se codifica utilizando 12 bits. Esta señal se almacena en una memoria intermedia donde es sometida a una etapa de pre procesado, siendo registrada a continuación en una cinta de alta densidad de 10.4 GB a velocidad de 20.4 MB/s.
• El sensor dispone de un sistema de calibración a bordo, que utiliza una lámpara halógena de cuarzo que proporciona la radiación de referencia necesaria para comprobar el estado de los diferentes espectrómetros.
• A lo largo de los últimos años, el sensor ha ido mejorando sus prestaciones en cuanto a la relación señal-ruido, como se muestra en la Figura 2.4 que describe la evolución de la relación SNR del sensor a lo largo de los últimos años.
Proyecto fin de carrera
-21-
Sergio Sánchez Martínez
2.3. Técnicas de análisis hiperespectral y necesidad de paralelismo
La mayoría de las técnicas de análisis hiperespectral desarrolladas hasta la fecha presuponen que la medición obtenida por el sensor en un determinado píxel viene dada por la contribución de diferentes materiales que residen a nivel sub-píxel. El fenómeno de la mezcla puede venir ocasionado por una insuficiente resolución espacial del sensor, pero lo cierto es que este fenómeno ocurre de forma natural en el mundo real, incluso a niveles microscópicos, por lo que el diseño de técnicas capaces de modelar este fenómeno de manera adecuada resulta imprescindible. No obstante, las técnicas basadas en este modelo son altamente costosas desde el punto de vista computacional. A continuación, detallamos las características genéricas de las técnicas basadas en este modelo y hacemos énfasis en la necesidad de técnicas paralelas para optimizar su rendimiento computacional.
2.3.1. Técnicas basadas en el modelo lineal de mezcla
El modelo lineal de mezcla expresa los píxeles mezcla [11] como una combinación lineal de firmas asociadas a componentes espectralmente puros (llamados endmembers) en la imagen [12]. Este modelo ofrece resultados satisfactorios cuando los componentes que residen a nivel sub-píxel aparecen espacialmente separados, situación en la que los fenómenos de absorción y reflexión de la radiación electromagnética incidente pueden ser caracterizados siguiendo un patrón estrictamente lineal. En la actualidad, el modelo lineal de mezcla es el más utilizado en análisis hiperespectral, debido a su sencillez y generalidad.
Proyecto fin de carrera
-22-
Sergio Sánchez Martínez
Figura 2.5 Interpretación gráfica del modelo lineal de mezcla
El modelo lineal de mezcla puede interpretarse de forma gráfica en un espacio bidimensional utilizando un diagrama de dispersión entre dos bandas poco correlacionadas de la imagen, tal y como se muestra en la Figura 2.5. En la misma, puede apreciarse que todos los puntos de la imagen quedan englobados dentro del triángulo formado por los tres puntos más extremos (elementos espectralmente más puros). Los vectores asociados a dichos puntos constituyen un nuevo sistema de coordenadas con origen en el centroide de la nube de puntos, de forma que cualquier punto de la imagen puede expresarse como combinación lineal de los puntos más extremos, siendo estos puntos son los mejores candidatos para ser seleccionados como endmembers [13]. El paso clave a la hora de aplicar el modelo lineal de mezcla consiste en identificar de forma correcta los elementos extremos de la nube de puntos N-dimensional. En la literatura reciente se han propuesto númerosas aproximaciones al problema de identificación de endmembers en imágenes hiperespectrales. Por ejemplo, el método Píxel Purity Index (PPI) [9] se basa en la generación repetitiva de vectores unitarios con orientación aleatoria en la nube de puntos de forma que todos los puntos de la imagen hiperespectral se proyectan sobre cada vector unitario, identificando los puntos extremos en la dirección definida por dicho vector e incrementando un contador asociado a dichos puntos. Tras la ejecución de un número amplio de iteraciones, se obtiene como resultado una imagen de pureza, formada por
Endmember s Endmember v Endmember u mezcla: 1/2 u + 1/2 s mezcla: 1/2 u + 1/2 v centroide: 1/3 u + 1/3 v + 1/3 s s u v
Banda i
B
a
n
d
a
j
mezcla: c1 s + c2 v = –c3 uProyecto fin de carrera
-23-
Sergio Sánchez Martínez
los índices asociados a cada uno de los píxeles de la imagen, a partir de la cual se extrae un conjunto final de endmembers utilizando técnicas de análisis y visualización interactiva. Por su parte, el método N-FINDR utiliza un procedimiento totalmente automático para extraer endmembers basado en identificar los vértices del simplex de mayor volumen que puede formarse en la nube de puntos.
2.3.2. Necesidad de paralelismo
Conviene destacar que las técnicas de análisis hiperespectral anteriormente descritas se basan en la realización de operaciones matriciales que resultan muy costosas desde el punto de vista computacional [14]. Sin embargo, el carácter repetitivo de estas operaciones las hace altamente susceptibles de ser implementadas en diferentes tipos de arquitecturas paralelas, permitiendo así un incremento significativo de su rendimiento en términos computacionales y dotando a dichas técnicas de la capacidad de producir una respuesta rápida. Esta tarea es clave para la explotación de dichas técnicas en aplicaciones que requieren una respuesta en tiempo casi real.
Las técnicas de computación paralela han sido ampliamente utilizadas para llevar a cabo tareas de procesamiento de imágenes de gran dimensionalidad, facilitando la obtención de tiempos de respuesta muy reducidos y pudiendo utilizar diferentes tipos de arquitecturas [15-17]. En la actualidad, es posible obtener arquitecturas paralelas de bajo coste mediante la utilización de GPUs de última generación que cuentan con múltiples procesadores.
2.3.3. El papel de las GPUs
La extracción de endmembers es una tarea crucial en la explotación de datos hiperespectrales. En la última década se han desarrollado muchos algoritmos para la extracción automática de endmembers desde un conjunto de datos hiperespectrales, incluidos PPI, N-FINDR, análisis de componentes vértices, o IEA. Estas técnicas tratan los datos hiperespectrales no como una imagen sino como una lista desordenada de dimensiones espectrales, donde las coordenadas espaciales se pueden cambiar de forma aleatoria sin que esto afecte al proceso de búsqueda de
Proyecto fin de carrera
-24-
Sergio Sánchez Martínez
endmembers.
A pesar de que el desarrollo espacial y espectral es una promesa para el análisis científico de imágenes terrestres, introduce un nuevo reto de procesamiento particularmente para conjunto de datos de alta dimensionalidad. Desde un punto de vista computacional cada algoritmo muestra un patrón de acceso a los datos regular y que muestra un paralelismo inherente a muchos niveles: a nivel de vectores de píxeles, a nivel de información espectral e incluso a nivel de tarea. Como resultado se asocian con sistemas paralelos compuestos por CPUs (por ejemplo clusters Beowulf). Desafortunadamente estos sistemas son caros y difíciles de adaptar a bordo de escenarios de procesamiento de sensación remota.
Un nuevo desarrollo en el campo de la computación surge con los procesadores gráficos programables (GPUs). Guiadas por la creciente demanda de la industria de los videojuegos, las GPUs han evolucionado como sistemas programables altamente paralelos. Sin embargo la arquitectura de las GPUs no encaja necesariamente con todos los tipos de computación paralela, el rango de aplicaciones candidatas va más allá del dominio del renderizado de gráficos.
En especial, el siempre creciente requerimiento computacional introducido por el estado actual de los algoritmos de imágenes hiperespectrales pueden beneficiarse de este hardware y tomar ventaja de su poco peso y bajo coste de sus unidades, lo que lo hace llamativo para el procesamiento de datos a bordo por un coste mucho más bajo del que tienen otros dispositivos hardware como las FPGAs.
Proyecto fin de carrera
-25-
Sergio Sánchez Martínez
3. Tarjetas gráficas programables (GPUs)
En este capítulo hablamos de cómo han ido evolucionando las GPUs programables, de los recursos que ofrecen y su capacidad de computo. Introduciremos una serie de conceptos para lograr entender cómo se lleva a cabo el procesamiento en una GPU mediante CUDA. Describiremos el hardware de la tarjeta 8800 GTX (G80) con la que se ha realizado el proyecto y finalmente trataremos el lenguaje CUDA en si dando unas nociones básicas para llevar a cabo cualquier proyecto con este lenguaje.
3.1. Las GPUs como un dispositivo de computación de datos en paralelo.
Desde un tiempo a esta parte, las GPUs programables han evolucionado como un elemento con una gran carga de trabajo, como podemos apreciar en la Figura 3.1. Con múltiples núcleos dirigidos por un gran ancho de banda de memoria, hoy por hoy las GPUs ofrecen prestaciones muy elevadas para procesamiento gráfico y científico [19-22].
Figura 3. 1 Operaciones en coma flotante por segundo para CPU y GPU.
Antes de examinar en detalle la arquitectura de una GPU GeForce 8800 GTX de NVidia (http://www.nvidia.com), consideramos relevante explicar cómo han
Proyecto fin de carrera
-26-
Sergio Sánchez Martínez
funcionado las operaciones en un pipeline de una GPU clásica a lo largo de los años. No obstante, para entender este proceso, también debemos introducir los conceptos de vertex shaders y los píxel shaders.
3.1.1. Vertex shaders y píxel shaders
Los shaders son pequeños programas que se encargan del procesamiento de vértices (vertex shaders) y de píxeles (píxel shaders). La principal ventaja es que, como su naturaleza lo indica, pueden ser programados por el desarrollador, otorgando una flexibilidad que hasta antes de la aparición de los shaders era algo impensable. Recursos como las operaciones condicionales o los saltos se utilizan de forma similar que en los lenguajes más conocidos. Sin los shaders, muchos de los efectos eran realizados en conjunto con la unidad de procesamiento central, disminuyendo en gran medida el rendimiento y limitando el avance a nivel gráfico de los mismos.
Un vertex shader es una función que recibe como parámetro un vértice. Sólo trabaja con un vértice a la vez, y no puede eliminarlo, sólo transformarlo. Para ello, modifica propiedades del mismo para que repercutan en la geometría del objeto al que pertenece. Con esto se pueden lograr ciertos efectos específicos, como los que tienen que ver con la deformación en tiempo real de un elemento; por ejemplo, el movimiento de una ola. Donde toma una gran importancia es en el tratamiento de las superficies curvas.
En cambio, un píxel shader básicamente especifica el color de un píxel. Este tratamiento individual de los píxeles permite que se realicen cálculos principalmente relacionados con la iluminación del elemento del cual forman parte en la escena, y en tiempo real.
La incorporación de los píxel shaders y vertex shaders permite a los programadores una mayor libertad a la hora de diseñar gráficos en tres dimensiones, ya que puede tratarse a cada píxel y cada vértice por separado. De esta manera, los efectos especiales y de iluminación pueden crearse mucho más detalladamente, sucediendo lo mismo con la geometría de los objetos.
Proyecto fin de carrera
-27-
Sergio Sánchez Martínez
3.1.2. Secuencia o pipeline clásico de procesamiento en una GPU
Cuando revisamos las arquitecturas hardware, el flujo de datos, y las operaciones pipeline, a menudo es bueno empezar por el nivel más alto, donde los datos llegan desde la CPU a la GPU, y el proceso se desarrolla hacia abajo a través de múltiples fases de procesamiento hasta que un píxel es dibujado definitivamente en la pantalla. Para situarnos, las GPUs han utilizado diseños pipeline tradicionales, como los que aparecen ilustrados en la Figura 3.2.
Figura 3. 2 Pipeline clásico de procesamiento para una GPU.
Después de que la GPU recibe los datos vertex (vértices) desde el host (CPU), la fase vertex se ejecuta en primer lugar. La función de fijado transforma la imagen y el hardware de luminosidad operado en esta fase se lleva a cabo; entonces los píxeles shaders programables, y el control de flujo dinámico de los modelos shaders entran en juego. El siguiente paso en el pipeline clásico es la configuración, donde los vértices son ensamblados dentro de primitivas como triángulos, líneas o puntos. Las primitivas son convertidas por la fase de “rasterización” en fragmentos de píxeles (o simplemente fragmentos), pero no son considerados píxeles completos en esta fase. Los fragmentos están sometidos a muchas otras operaciones como sombreado, Z-testing, la posible mezcla en el buffer frame, y el antialiasing. Los
Proyecto fin de carrera
-28-
Sergio Sánchez Martínez
fragmentos son finalmente considerados píxeles cuando han sido escritos en el buffer frame.
A continuación, la siguiente fase es la de píxel shader, que debería ser denominada técnicamente como fase fragment shader, pero utilizamos la notación estándar en la literatura [19-22] debido a su aceptación. En el pasado, los fragmentos sólo podían haber tenido valores de color aplicados de textura simple. Hoy en día, la capacidad de sombreado de un píxel programado de la GPU permite númerosos efectos de sombreado para ser aplicados mientras se trabaja de acuerdo con métodos complejos de multitextura. Específicamente, los fragmentos sombreados (con color y valores Z) desde esta fase píxel son enviados al ROP (Raster Operations). La fase ROP es donde se chequea el buffer Z para asegurar que sólo los fragmentos visibles son procesados rápidamente, y los fragmentos visibles, si son parcialmente transparentes, son mezclados con el buffer de frame existente, junto con los píxeles y aplicándoles antialiased. El píxel procesado final es enviado a la memoria buffer para ser escaneado y visualizado en el monitor [19].
3.1.3. Evolución del uso de GPUs en aplicaciones científicas
La principal razón que justifica la gran popularidad de las arquitecturas GPU en aplicaciones científicas es el hecho de que la GPU está especializada para cómputo intensivo, computación paralela elevada (exactamente sobre lo que trata el renderizado de gráficos) y por tanto se designan más transistores dedicados al procesamiento de datos, que a la recolección de datos y control de flujo como se muestra en la Figura 3.3.
Proyecto fin de carrera
-29-
Sergio Sánchez Martínez
Figura 3. 3 La GPU proporciona más transistores para el procesamiento de datos.
Más específicamente, la GPU está especialmente pensada para direccionar problemas que pueden ser expresados como computaciones de datos paralelos (el mismo programa es ejecutado en muchos elementos de datos en paralelo) con gran intensidad aritmética (el ratio de operaciones aritméticas respecto a operaciones de memoria). Como el mismo programa es ejecutado para cada elemento de datos, hay menos requisitos para un flujo de control sofisticado; y como es ejecutado en muchos elementos de datos y tiene gran intensidad aritmética, la latencia de acceso a memoria puede ser ocultada con cálculos, en vez de datos muy grandes de caché [20].
El procesamiento de datos paralelos acota los elementos de datos al procesamiento paralelo de hilos. Muchas aplicaciones que procesan grandes conjuntos de datos como arrays pueden usar un modelo de programación de datos paralelos para acelerar los cálculos. En renderizado 3D los conjuntos de píxeles y vértices se asignan a hilos paralelos. De la misma manera, aplicaciones de procesamiento de imágenes y media como postprocesado de imágenes renderizadas, codificación y decodificación de video, escalado de imágenes, visión estéreo, y patrones de reconocimiento pueden asociar bloques de la imagen y píxeles a hilos de procesamiento paralelo. De hecho, muchos algoritmos fuera del campo del renderizado como el procesamiento de señales, simulaciones físicas finanzas o biología, se aceleran con el procesamiento de datos en paralelo.
Proyecto fin de carrera
-30-
Sergio Sánchez Martínez
Hasta la fecha, sin embargo, a pesar de acceder a todo el poder de computación contenido en al GPU y usarlo eficientemente para aplicaciones científicas, seguía siendo difícil obtener las siguientes pautas:
• La GPU solamente podía ser programada a través de la API (Application Programming Interface) gráfica; esto provocaba que la curva de aprendizaje para un desarrollador principiante fuese muy elevada, ya que tenía que trabajar con una API inadecuada, que no estaba adaptada a la aplicación científica.
• La DRAM de la GPU podía ser leída de manera general (los programas de GPU pueden obtener elementos de datos de cualquier parte de la DRAM) pero no se podía escribir de manera general (los programas de GPU no pueden esparcir la información a cualquier parte de la DRAM), eliminando mucha de la flexibilidad de programación ya disponible en la CPU.
• Algunas aplicaciones tenían en problema del “cuello de botella”, debido al ancho de banda de la memoria DRAM, utilizando escasamente el poder computacional de la GPU.
En este sentido, una de las principales motivaciones del presente PFC es demostrar que dichas limitaciones en la actualidad pueden superarse mediante la utilización de la arquitectura CUDA para procesamiento de datos científicos en la GPU. Dicho aspecto será abordado en detalle en el siguiente subapartado del presente capítulo de la memoria.
3.2. CUDA: Una Nueva Arquitectura para el Cálculo en la GPU
CUDA viene del inglés Compute Unified Device Architecture y es una nueva arquitectura hardware y software, diseñada para dar y manejar procesamientos en la GPU como un elemento de computación de datos paralelos sin la necesidad de mapearlos a una API de gráficos. Está disponible para las versiones GeForce 8 Series, Quadro FX 5600/4600, y Tesla. El mecanismo de multitarea del sistema
Proyecto fin de carrera
-31-
Sergio Sánchez Martínez
operativo es responsable de manejar el acceso a la GPU mediante CUDA, y las aplicaciones gráficas funcionan de forma simultánea. A continuación describimos el pipeline unificado del que disponen las actuales GPUs de NVIDIA y que puede ser explotado de forma eficiente mediante CUDA, así como la arquitectura completa de la GeForce 8800 GTX,. El apartado finaliza describiendo los diferentes modelos de programación en CUDA.
3.2.1. Pipeline unificado
A partir del modelo de pipeline clásico, con sus flujos de datos empezando en lo más alto, donde los vértices con varios atributos, índices, comandos, y texturas son pasados a la GPU desde la CPU. Las fases de procesamiento mayores siguen una manera lineal segura incluyendo vertex shading, píxel shading, operaciones raster, (que son operaciones a través de las cuales un área espacial queda dividida en celdas regulares, en las que cada una de las cuales presentan unos atributos o valor, como pueden ser la altitud, reflectancia, etc.) y escritura de píxeles en el buffer frame.
Con este pipeline unificado y la arquitectura “shader”, el diseño de la GPU GeForce 8800 reduce significativamente el número de fases del pipeline y cambia el flujo secuencial para estar más orientado a bucle. Las entradas son alimentadas en la parte alta del núcleo shader unificado, y las salidas son escritas en registros y entonces vuelven otra vez a la parte alta del núcleo shader para la próxima operación. Como resultado, en el diagrama GPU unificado generalizado que se muestra en la Figura 3.4, los flujos de datos bajan secuencialmente por el pipeline a través de diferentes tipos “shader”. La figura de la derecha representa un núcleo “shader” unificado con uno o más procesadores “shader” unificados estandarizados.
Proyecto fin de carrera
-32-
Sergio Sánchez Martínez
Figura 3. 4 Pipeline clásico frente a pipeline unificado.
Como puede apreciarse en la Figura 3.4, los datos vienen de la parte superior izquierda del diseño unificado (como vértices), y son llevados al núcleo shader para su procesamiento, y los resultados son enviados de vuelta a la parte superior del núcleo shader, donde son llevados otra vez, procesados otra vez, mandados de vuelta a la parte superior, y así hasta que todas las operaciones shader son ejecutadas y el fragmento de píxel se pasa al subsistema ROP [19].
3.2.2. Modelo de programación CUDA
Antes de profundizar en el modelo de programación empleado por CUDA, destacamos que la pila del software de CUDA se compone de varias capas, tal y como muestra la Figura 3.5. En concreto, dichas capas son un controlador de hardware, una API y su runtime, y dos librerías matemáticas de alto nivel para uso común, CUFFT y CUBLAS. El hardware ha sido diseñado para soportar controladores ligeros y capas runtime, dando como resultado una ejecución óptima. En este sentido, la API de CUDA es una extensión del lenguaje de programación C, lo cual hace que tenga una curva de aprendizaje mínima.
Proyecto fin de carrera
-33-
Sergio Sánchez Martínez
Figura 3. 5 Pila software de CUDA
Por otra parte, CUDA ofrece un direccionamiento de carácter general para la memoria DRAM como ilustra la Figura 3.6. Este modelo de direccionamiento permite obtener mayor flexibilidad en la programación, en el sentido de que ofrece tanto la operación de reparto de datos como la de obtención de estos. Desde una perspectiva de programación, esto se traduce en la habilidad de leer y escribir datos en cualquier lugar de la DRAM, exactamente igual que en la CPU [20].
Proyecto fin de carrera
-34-
Sergio Sánchez Martínez
Figura 3. 6 Operaciones de memoria gather (dispersión) y scatter (reunión)
Por otra parte, CUDA ofrece un direccionamiento de carácter general para la memoria DRAM como ilustra la Figura 3.7. Este modelo de direccionamiento permite obtener mayor flexibilidad en la programación, en el sentido de que ofrece tanto la operación de reparto de datos como la de obtención de estos. Desde una perspectiva de programación, esto se traduce en la habilidad de leer y escribir datos en cualquier lugar de la DRAM, exactamente igual que en la CPU [20].
Proyecto fin de carrera
-35-
Sergio Sánchez Martínez
3.3. Procesamiento
En la siguiente sección presenta a la GPU como un coprocesador multihilo para la CPU, seguidamente se exponen los diferentes mecanismos de los que se hace uso para llevar a cabo el procesamiento en la GPU, estos son los hilos de ejecución, los bloques en los que se organizan estor hilos y los llamados grid en los que se estructuran estos bloques. La sección finaliza con el modelo de memoria utilizado por CUDA.
3.3.1. Un Coprocesador Multithread
Cuando se programa con CUDA, la GPU se ve como un dispositivo de cálculo (device) capaz de ejecutar un gran número de hilos en paralelo. Esta opera como un coprocesador de la CPU principal, o host. En otras palabras, los datos paralelos, cálculo intensivo de porciones de aplicaciones ejecutándose en el host son cargados en el device. De forma más precisa, una parte de una aplicación que se ejecuta muchas veces, pero con datos diferentes e independientes, puede ser aislada en una función que es ejecutada en el device como muchos hilos independientes. Como dicha función es compilada, la instrucción obtenida a partir del device (en nuestro caso, la GPU) y el programa resultante, llamado kernel, se descargan en el device. Tanto el host como el device mantienen su propia DRAM, referidas como memoria del host y memoria del device respectivamente. Una puede copiar datos de una memoria a la otra a través de llamadas a una API optimizada, que usa el Acceso Directo a Memoria (DMA) del device [20].
3.3.2. Hilos, bloques y grids
El tratamiento por lotes de los hilos que ejecuta el kernel está organizado como un grid de bloques de hilos, ilustrado en la Figura 3.8. Un bloque de hilos es un lote de hilos que pueden cooperar juntos compartiendo datos eficientemente a través de algunas memorias rápidas de compartición de datos y sincronizando sus ejecuciones para coordinar los accesos a memoria. De forma precisa, uno puede especificar
Proyecto fin de carrera
-36-
Sergio Sánchez Martínez
puntos de sincronización en el kernel, donde los hilos en un bloque están suspendidos hasta que todos ellos alcancen el punto de sincronización. Cada hilo es identificado por su identificador de hilo (thread ID), que es el número de hilo con el bloque [20].
Hay un número límite como máximo de hilos que un bloque puede contener (512 hilos concretamente). Sin embargo, los bloques de misma dimensión y tamaño que ejecutan el mismo kernel pueden ser tratados por lotes de forma conjunta, en un grid de bloques, así que el número total de hilos puede ser lanzado en una única invocación del kernel es mucho más grande. Esto se debe al gasto de reducir la cooperación entre hilos, porque los hilos en diferentes bloques del mismo grid no pueden comunicarse ni sincronizarse con los de los demás. Este modelo permite a los kernels ejecutarse eficientemente sin recompilación en varios devices con diferentes capacidades paralelas: un device puede ejecutar todos los bloques de un grid secuencialmente si tiene algunas capacidades, o en paralelo si tiene muchas, o normalmente una combinación de ambas [20]. La Figura 3.8 muestra como cada kernel se ejecuta como un grid de bloques de hilos.
Proyecto fin de carrera
-37-
Sergio Sánchez Martínez
Figura 3. 8 El host emite al device una sucesión de invocaciones de kernels. Cada kernel se ejecuta como un grupo de hilos organizados como un grid de bloques de hilos.
3.3.3. Modelo de memoria
Un hilo que se ejecute en el device tiene solo acceso a la DRAM del device y a la memoria on-chip a través de los siguientes espacios de memoria (Tabla 3.1) [20], como se muestra en la Figura 3.9.
Tabla 3. 1 Lecturas y escrituras en los diferentes tipos de memorias
Los espacios de memoria global, constante y de textura pueden ser leídos o escritos por el host y perduran durante las distintas ejecuciones del kernel en la misma aplicación. Los espacios de memoria global, constante y de textura se optimizan para diferentes usos de la memoria. Además la memoria de texturas ofrece diferentes modos de direccionamiento, así como de filtrado de datos, para diferentes formatos de datos.
Proyecto fin de carrera
-38-
Sergio Sánchez Martínez
Figura 3. 9 Un hilo tiene acceso a la DRAM del device y a la memoria on-chip a través de un conjunto de espacios de memoria para varios propósitos.
3.4. Implementación hardware y modelo de ejecución
En esta sección se presenta la arquitectura hardware de la GPU utilizada en el proyecto y se explica el modelo de ejecución que sigue CUDA.
3.4.1. GeForce 8800GTX - 768 Mb DDR3 - PCI-Express 16X - Dual DVI
A lo largo de la presente memoria hemos cubierto muchos de los puntos básicos de la programación de GPUs de NVidia, así que ahora podemos echar un vistazo a los aspectos específicos de la arquitectura GeForce 8800 GTX [19], la tarjeta que estamos usando para realizar este PFC. La Figura 3.10 describe la arquitectura hardware de dicha tarjeta. Como podemos apreciar en la figura, el bloque de interfaz del host incluye buffers para recibir comandos, datos vertex, y texturas enviadas a la GPU desde el controlador gráfico ejecutándose en la CPU. Lo siguiente, es el ensamblador de entrada, que encuentra datos vertex desde los buffers y los convierte a formato de coma flotante 32, mientras que también genera varios índices que sirven de ayuda para llevar a cabo varias operaciones repetidas en los vértices y las primitivas, y para habilitar el instanciado.
Proyecto fin de carrera
-39-
Sergio Sánchez Martínez
Figura 3. 10 Arquitectura de la GPU GeForce 8800 GTX de NVidia.
A continuación la Tabla 3.2 muestra las características técnicas de la GPU:
Tabla 3. 2 Características técnicas de la GPU GeForce 8800 GTX de NVidia.
3.4.2. Modelo de ejecución
El dispositivo GPU es implementado como un conjunto de multiprocesadores como se puede ver en la Figura 3.11. Cada multiprocesador tiene una Instrucción Única (Single Instruction), y arquitectura de Datos Múltiples (Multiple Data
Proyecto fin de carrera
-40-
Sergio Sánchez Martínez
architecture ó SIMD): en cada ciclo de reloj dado, cada procesador del multiprocesador ejecuta la misma instrucción, pero opera en datos distintos. Los espacios de memoria local y global son implementados como regiones de la memoria del device. Cada multiprocesador accede a la cache de textura mediante una unidad de textura que implementa los diferentes modos de direccionamiento y filtros de datos [20].
Figura 3. 11 Conjunto de multiprocesadores SIMD con memoria compartida on-chip
Con respecto al modelo de ejecución en la GPU, conviene destacar que un grid de bloques de hilos es ejecutado en el device ejecutando uno ó más bloques en cada multiprocesador, usando porciones de tiempo: cada bloque se corta en grupos SIMD de hilos llamados warps (tramas), cada uno de estos warps contiene el mismo número de hilos, llamado warp size (que es de 32 hilos), y es ejecutado por el
Proyecto fin de carrera
-41-
Sergio Sánchez Martínez
multiprocesador en un modo SIMD; un programador de hilos selecciona periódicamente de un warp a otro, para maximizar el uso de los recursos de computación del multiprocesador. Una half-warp es o bien la primera o la segunda parte de un warp. La manera en que un bloque es dividido en warps es siempre la misma; cada warp contiene hilos consecutivos, incrementando los IDs de los hilos con el primer warp conteniendo el hilo 0.
Un bloque es procesado solamente por un multiprocesador, así que el espacio de memoria compartida reside en la memoria on-chip compartida, llevando a unos accesos a memoria muy rápidos. Los registros del multiprocesador están localizados entre los hilos del bloque. Si el número de registros usados por hilo, multiplicado por el número de hilos en el bloque, es mayor que el número total de registros por multiprocesador, el bloque no puede es ejecutado y el correspondiente kernel fallaría al lanzarse. Por otra parte, varios bloques pueden ser procesados por el mismo multiprocesador concurrentemente, situando los registros del multiprocesador y la memoria compartida entre los bloques.
La orden emitida de los bloques con el grid de bloques de hilos no está definida, y no hay un mecanismo de sincronización entre los bloques, así los hilos de dos bloques diferentes del mismo grid no pueden comunicarse de forma segura con los demás a través de la memoria global durante la ejecución del grid [20].
Finalmente, destacamos que el uso de múltiples GPUs, como las devices de CUDA, permite que una aplicación se ejecute en un sistema multi-GPU solamente si las GPUs son del mismo tipo. Si el sistema está en el modo SLI quizás, sólo una GPU puede ser usada como una device de CUDA ya que todas las GPUs están fusionadas en los niveles más bajos en la pila del driver. El modo SLI necesita estar apagado en el panel de control de CUDA para ser capaz de ver cada GPU como un device separado [20].
Si una instrucción no atómica ejecutada por un warp escribe en la misma posición ya sea de memoria global o compartida por más de un hilo de warp, el número de de escrituras serializadas que ocurran en esa posición así como el orden de las escrituras es indefinido, pero se garantiza que al menos una escritura tenga
Proyecto fin de carrera
-42-
Sergio Sánchez Martínez
éxito. Si una instrucción atómica ejecutada por un warp lee, modifica o escribe en una posición de memoria ya sea global o compartida por más de un hilo del warp, cada lectura, modificación o escritura en la posición ocurre de forma serializada aunque el orden es indefinido.
Por desgracia como muestra la Tabla 3.3 muestra GPU no cuenta con la capacidad de cómputo 1.1 sino con la 1.0 por lo que no soporta operaciones atómicas lo cual sería una gran ventaja a la hora de realizar nuestro algoritmo. A continuación se muestra una tabla con el número de multiprocesadores de cada GPU y de la versión de capacidad de cómputo de las mismas.
Tabla 3. 3 Muestra el número de multiprocesadores y la capacidad de cómputo de las diferentes GPUs de nVidia
3.4.3. Especificaciones generales
A continuación se listan una serie de especificaciones generales que se deben tener en cuenta a la hora de programar una GPU con CUDA para lograr una
Proyecto fin de carrera
-43-
Sergio Sánchez Martínez
ejecución más eficiente.
• El número máximo de hilos pro bloque es de 512.
• El tamaño máximo de las dimensiones x-, y-, y z- de un bloque de hilos es de 512.
• El tamaño máximo de cada dimensión de un grid es de 65535.
• El tamaño de un warp es de 32 hilos.
• El número de registros por multiprocesador es de 8192.
• La cantidad de memoria compartida para cada multiprocesador es de 16 KB organizada en 16 bancos.
• La cantidad total de memoria constante es de 64 KB.
• El conjunto de trabajo de cache para memoria constante es de 8 KB por multiprocesador.
• El conjunto de trabajo de cache para la memoria de textura es de 8 KB por multiprocesador.
• El número máximo de bloques activos por multiprocesador es de 8.
• El número máximo de warps activos por multiprocesador es de 24.
• El número máximo de hilos activos por multiprocesador es de 768.
• Para una referencia de textura destinada a un array unidimensional CUDA, la anchura máxima es de 213
• Para una referencia de textura destinada a un array bidimensional CUDA, la anchura máxima es de 216 y la altura máxima es de 215.
• Para una referencia de textura destinada a una memoria lineal, la anchura máxima es de 217.
Proyecto fin de carrera
-44-
Sergio Sánchez Martínez
nativas.
• Cada multiprocesador se compone de 8 procesadores, así que un multiprocesador es capaz de procesar los 32 hilos de un warp en 4 ciclos de reloj.