Volver a los cursos
AI032 Professional

Programación de procesadores masivamente paralelos: Un enfoque práctico

Este curso ofrece una introducción completa al cálculo en GPU y programación paralela utilizando el entorno CUDA C. Cubre arquitecturas de GPU, paralelismo de datos, gestión de hilos, optimización de memoria y consideraciones avanzadas de rendimiento, ilustradas mediante casos prácticos reales como la reconstrucción de resonancia magnética y la visualización molecular.

4.9
36.0h
569 estudiantes
0 me gusta
Inteligencia Artificial
Comenzar a aprender

Descripción del curso

📚 Resumen del contenido

Este curso ofrece una introducción completa al cálculo en GPU y al programación paralela utilizando el entorno CUDA C. Cubre arquitecturas de GPU, paralelismo de datos, gestión de hilos, optimización de memoria y consideraciones avanzadas de rendimiento, ilustradas mediante estudios de caso del mundo real como la reconstrucción de MRI y la visualización molecular.

Domine el arte del cálculo paralelo de alto rendimiento con una guía práctica y basada en la experiencia sobre CUDA y arquitecturas de GPU.

Autor: David B. Kirk, Wen-mei W. Hwu

Agradecimientos: Ian Buck, John Nickolls, equipo NVIDIA DevTech, Jensen Huang, David Luebke, Bill Bean, Simon Green, Mark Harris, Manju Hedge, Nadeem Mohammad, Brent Oster, Peter Shirley, Eric Young y Cyril Zeller.

🎯 Objetivos de aprendizaje

  1. Distinguir entre las filosofías de diseño y trayectorias de rendimiento de los multicore CPUs y los muchos-core GPUs.
  2. Identificar los componentes clave de una arquitectura de GPU moderna, incluyendo Multiprocesadores de flujo (SMs) y estructuras de memoria.
  3. Aplicar la Ley de Amdahl para calcular el aceleramiento teórico e identificar el impacto de cuellos de botella secuenciales.
  4. Contrastar las diferencias arquitectónicas entre pipelines fijos y arreglos procesadores unificados programables.
  5. Explicar el papel del "GPGPU" como paso intermedio y las restricciones de los primeros modelos de programación de shaders.
  6. Analizar cómo características de hardware como operaciones atómicas, sincronización por barrera y soporte de doble precisión permitieron la transición hacia un cálculo generalizado escalable.
  7. Identificar y aprovechar el paralelismo de datos dentro de algoritmos de multiplicación de matrices.
  8. Implementar la gestión de memoria del dispositivo, incluyendo asignación, transferencia de datos entre host y dispositivo y desasignación.
  9. Crear e iniciar kernels CUDA usando índices de hilos y configuraciones adecuadas de grilla/bloque.
  10. Diseñar jerarquías de hilos multidimensionales (grillas y bloques) para mapear estructuras de datos complejas a hardware de GPU.

🔹 Lección 1: Introducción al cómputo paralelo y arquitecturas de GPU

Resumen: Esta lección explora el cambio fundamental desde el cómputo secuencial hacia el paralelo, impulsado por las filosofías de diseño divergentes de CPUs y GPUs. Los estudiantes examinarán las trayectorias "Multicore" versus "Many-core", comprenderán la arquitectura de hardware que permite a las GPUs alcanzar un alto rendimiento y aprenderán las restricciones matemáticas del aceleramiento mediante la Ley de Amdahl.

Resultados de aprendizaje:

  • Distinguir entre las filosofías de diseño y trayectorias de rendimiento de los multicore CPUs y los muchos-core GPUs.
  • Identificar los componentes clave de una arquitectura de GPU moderna, incluyendo Multiprocesadores de Flujo (SMs) y estructuras de memoria.
  • Aplicar la Ley de Amdahl para calcular el aceleramiento teórico e identificar el impacto de cuellos de botella secuenciales.

🔹 Lección 2: La evolución y futuro del cómputo en GPU

Resumen: Esta lección traza el recorrido arquitectónico de la Unidad de Procesamiento Gráfico (GPU), desde su origen como hardware especializado de función fija para renderizar triángulos hasta su estado actual como potente procesador paralelo unificado y generalizado. Los estudiantes explorarán la transición de pipelines rígidos a shaders programables, el surgimiento del movimiento GPGPU y las arquitecturas escalables modernas que impulsan simulaciones científicas e ingenieriles actuales.

Resultados de aprendizaje:

  • Contrastar las diferencias arquitectónicas entre pipelines de función fija y arreglos procesadores unificados programables.
  • Explicar el papel del "GPGPU" como paso intermedio y las restricciones de los primeros modelos de programación de shaders.
  • Analizar cómo características de hardware como operaciones atómicas, sincronización por barrera y soporte de doble precisión permitieron la transición hacia un cálculo generalizado escalable.

🔹 Lección 3: Estructura de programas CUDA y gestión de memoria

Resumen: Esta lección cubre la arquitectura fundamental de un programa CUDA, destacando la distinción entre ejecución en Host (CPU) y Device (GPU). Los estudiantes aprenderán a identificar el paralelismo de datos en operaciones matriciales, gestionar espacios de memoria separados usando la API CUDA y organizar la ejecución paralela mediante una jerarquía de grillas, bloques y hilos usando el estilo Single-Program, Multiple-Data (SPMD).

Resultados de aprendizaje:

  • Identificar y aprovechar el paralelismo de datos dentro de algoritmos de multiplicación de matrices.
  • Implementar la gestión de memoria del dispositivo, incluyendo asignación, transferencia de datos entre host y dispositivo y desasignación.
  • Crear e iniciar kernels CUDA usando índices de hilos y configuraciones adecuadas de grilla/bloque.

🔹 Lección 4: Hilos y planificación avanzados en CUDA

Resumen: Esta lección explora la organización jerárquica de hilos en CUDA, centrándose en cómo el índice multidimensional se mapea a datos físicos y recursos de hardware. Detalla los mecanismos de sincronización por barrera y escalabilidad transparente, concluyendo con los principios arquitectónicos de asignación de hilos y planificación basada en warps utilizados para lograr tolerancia a latencias en cómputo de alto rendimiento.

Resultados de aprendizaje:

  • Diseñar jerarquías de hilos multidimensionales (grillas y bloques) para mapear estructuras de datos complejas a hardware de GPU.
  • Implementar un índice de datos preciso usando variables integradas de CUDA (blockIdx, threadIdx, blockDim).
  • Aplicar la sincronización por barrera para garantizar la integridad de los datos manteniendo la escalabilidad transparente en diferentes arquitecturas de GPU.

🔹 Lección 5: Optimización de memoria y tiling de memoria compartida

Resumen: Esta lección explora cómo el ancho de banda de memoria y las limitaciones de recursos actúan como cuellos de botella principales en el cómputo paralelo. Detalla el uso del "tiling" para reducir el tráfico de memoria global y explica el papel crítico de las barreras de sincronización (__syncthreads()) y la elección estratégica entre registros y memoria compartida para optimizar el rendimiento.

Resultados de aprendizaje:

  • Analizar cómo los límites de registros y memoria compartida determinan el nivel de paralelismo (ocupación) en un kernel.
  • Cuantificar la reducción del consumo de ancho de banda de memoria global lograda mediante técnicas de tiling.
  • Identificar la necesidad de funciones de sincronización para mantener la integridad de los datos durante el acceso a memoria compartida.

🔹 Lección 6: Análisis de rendimiento y ejecución SIMT

Resumen: Esta lección explora los aspectos arquitectónicos y algorítmicos esenciales para optimizar kernels CUDA. Transita desde modelos de ejecución básicos —específicamente la unidad Single-Instruction, Multiple-Thread (SIMT) y la partición de warp— hacia técnicas avanzadas de optimización de rendimiento, incluyendo coalescencia de memoria, multiplicación de matrices con tiling y la partición dinámica de recursos del Streaming Multiprocessor (SM).

Resultados de aprendizaje:

  • Analizar el mapeo de bloques de hilos multidimensionales al orden lineal de ejecución de warp del hardware.
  • Evaluar y minimizar la divergencia de flujo de control en algoritmos de reducción paralela.
  • Optimizar el ancho de banda de memoria global implementando patrones de acceso coalescido y con tiling.

🔹 Lección 7: Aritmética de punto flotante y precisión numérica

Resumen: Esta lección cubre la arquitectura fundamental de los números de punto flotante, centrándose en los componentes del estándar IEEE 754: signo, exponente codificado en exceso y mantisa normalizada. Los estudiantes explorarán cómo estas patrones de bits se mapean a una línea numérica discreta y cómo las limitaciones de esta representación afectan la precisión de algoritmos complejos como sumatorias a gran escala.

Resultados de aprendizaje:

  • Descomponer el formato de punto flotante para calcular valores numéricos a partir de patrones de bits usando representación normalizada y codificación en exceso.
  • Visualizar la distribución de números representables en una línea numérica y explicar el impacto de la asignación de bits entre exponente y mantisa.
  • Cuantificar la inexactitud numérica usando ULP y identificar cómo diferentes modos de redondeo contribuyen al error.

🔹 Lección 8: Estudio de caso: Paralelización de la reconstrucción de MRI

Resumen: Esta lección explora la paralelización de la reconstrucción avanzada de imágenes por resonancia magnética (MRI) en GPUs. Se centra en el proceso iterativo de reconstrucción para trayectorias no cartesianas, optimizando específicamente el kernel computacionalmente intensivo F^H d mediante transformaciones de bucles, gestión de memoria constante, reorganización de disposición de datos y el uso de funciones trigonométricas aceleradas por hardware.

Resultados de aprendizaje:

  • Comprender la transición desde la reconstrucción basada en FFT cartesiana hacia algoritmos iterativos basados en resolutores lineales para datos de espacio k no cartesianos.
  • Aplicar la división de bucles (loop fission) y el intercambio de bucles (loop interchange) para transformar código C secuencial en una estructura adecuada para el mapeo masivo de hilos CUDA.
  • Optimizar el rendimiento de memoria usando fragmentación de memoria constante y disposiciones de datos Array-of-Structs (AoS).

🔹 Lección 9: Estudio de caso: Visualización molecular y ejecución multi-GPU

Resumen: Esta lección explora la aplicación práctica del cómputo en GPU a la visualización molecular, específicamente utilizando el método de Suma Directa de Coulomb (DCS) para calcular mapas de potencial electrostático. Los estudiantes pasarán desde una implementación básica de kernel hasta versiones altamente optimizadas que aprovechan el desenrollado de instrucciones, coalescencia de memoria y relleno.

Resultados de aprendizaje:

  • Implementar un kernel de Suma Directa de Coulomb (DCS) usando memoria constante CUDA y técnicas de ocultamiento de latencia de memoria global.
  • Optimizar el rendimiento del kernel mediante desenrollado de instrucciones y reutilización de cálculos comunes de coordenadas.
  • Aplicar estrategias de coalescencia de memoria y relleno para alinear accesos de memoria global de GPU con el máximo ancho de banda.

🔹 Lección 10: Pensamiento computacional y selección de algoritmos paralelos

Resumen: Esta lección explora la transición desde el pensamiento secuencial hacia la resolución de problemas paralelos, enfocándose en los objetivos de la programación paralela y la selección estratégica de algoritmos. Los estudiantes aprenderán a descomponer problemas en unidades paralelizables, aplicar el pensamiento computacional para cerrar la brecha entre ciencia del dominio y arquitectura de hardware, y evaluar el rendimiento de algoritmos.

Resultados de aprendizaje:

  • Identificar los objetivos principales de la programación paralela y calcular el aceleramiento teórico usando la Ley de Amdahl.
  • Diferenciar entre descomposición a nivel de tarea y a nivel de datos, y aplicar estrategias centradas en átomos (scatter) versus centradas en rejilla (gather).
  • Evaluar y seleccionar algoritmos paralelos según criterios como ancho de banda de memoria, complejidad computacional y restricciones arquitectónicas.

🔹 Lección 11: Introducción al modelo de programación OpenCL

Resumen: Esta lección presenta OpenCL como un marco para el cómputo paralelo heterogéneo, centrándose en su modelo de paralelismo de datos y abstracción jerárquica de hardware. Los estudiantes aprenderán a mapear los NDRange y estructuras de memoria de OpenCL a sus equivalentes CUDA y dominarán la gestión del lado host de dispositivos mediante un modelo de compilación dinámica.

Resultados de aprendizaje:

  • Mapear el paralelismo y jerarquías de memoria de OpenCL a arquitecturas específicas de CUDA (por ejemplo, mapear Work-groups a Bloques y Memoria Local a Memoria Compartida).
  • Implementar funciones kernel de OpenCL y gestionar el entorno de ejecución del lado host usando Contextos y Colas de Comandos.
  • Ejecutar el flujo de trabajo de compilación dinámica para compilar kernels desde código fuente en tiempo de ejecución.

🔹 Lección 12: Características modernas de GPU y perspectiva futura

Resumen: Esta lección explora la evolución arquitectónica y funcional de las GPUs, centrándose en la transición hacia una gestión de memoria sofisticada, capacidades mejoradas de ejecución de kernels y mayor rendimiento de núcleos. Los estudiantes examinarán cómo características como el Espacio de Memoria Unificada de Dispositivo y las llamadas de funciones a nivel de kernel transforman la GPU en un procesador generalizado.

Resultados de aprendizaje:

  • Explicar la importancia de la Evolución de la Arquitectura de Memoria y la transición hacia un Espacio de Memoria Unificada de 64 bits para dispositivos.
  • Analizar cómo las Operaciones Atómicas Mejoradas y las Llamadas de Funciones a Nivel de Kernel permiten la implementación de estructuras de datos y algoritmos complejos.
  • Evaluar los impactos de rendimiento de la Ejecución Simultánea de Kernels, la mejora del rendimiento en doble precisión y la Eficiencia del Flujo de Control en entornos de GPU modernos.