CUDA

CUDA son las siglas de Compute Unified Device Architecture (Arquitectura Unificada de Dispositivos de Cómputo) que hace referencia a una plataforma de computación en paralelo que incluye un compilador y un conjunto de herramientas de desarrollo creadas por Nvidia que permiten a los programadores usar una variación del lenguaje de programación C (CUDA C) para codificar algoritmos en GPU de Nvidia.

CUDA
Información general
Tipo de programa GPGPU
Desarrollador NVIDIA Corporation
Lanzamiento inicial 23 de junio de 2007
Licencia Propietaria, Freeware
Versiones
Última versión estable 11.7.0 ( 29 de julio de 2021 (1 año, 2 meses y 8 días))
Enlaces

Por medio de wrappers se puede usar Python, Fortran, Julia y Java en vez de C/C++.

Funciona en todas las GPU Nvidia de la serie G8X en adelante, incluyendo GeForce, Quadro, ION y la línea Tesla.[1] Nvidia afirma que los programas desarrollados para la serie GeForce 8 también funcionarán sin modificaciones en todas las futuras tarjetas Nvidia, gracias a la compatibilidad binaria provista por el conjunto de instrucciones PTX (Parallel Thread Execution).[2]

CUDA intenta explotar las ventajas de las GPU frente a las CPU de propósito general utilizando el paralelismo que ofrecen sus múltiples núcleos, que permiten el lanzamiento de un altísimo número de hilos simultáneos. Por ello, si una aplicación está diseñada utilizando numerosos hilos que realizan tareas independientes (que es lo que hacen las GPU al procesar gráficos, su tarea natural), una GPU podrá ofrecer un gran rendimiento en campos que podrían ir desde la biología computacional a la criptografía, por ejemplo.

El primer SDK se publicó en febrero de 2007 en un principio para Windows, Linux, y más adelante en su versión 2.0 para macOS. Actualmente se ofrece para Windows XP/Vista/7/8/10,[3] para Linux 32/64 bits[4] y para macOS.[5]

Historia

En 2003, un equipo de investigadores dirigido por Ian Buck presentó Brook, el primer modelo de programación ampliamente adoptado para extender C con construcciones paralelas de datos. Ian Buck luego se unió a NVIDIA y lideró el lanzamiento de CUDA en 2006, la primera solución del mundo para computación general en GPU. [6]

Ejemplo de flujo de procesamiento CUDA
1. Se copian los datos de la memoria principal a la memoria de la GPU
2. La CPU encarga el proceso a la GPU
3. La GPU lo ejecuta en paralelo en cada núcleo
4. Se copia el resultado de la memoria de la GPU a la memoria principal

Ventajas

CUDA presenta ciertas ventajas sobre otros tipos de computación sobre GPU utilizando APIs gráficas.

  • Lecturas dispersas: se puede consultar cualquier posición de memoria.
  • Memoria compartida: CUDA pone a disposición del programador un área de memoria de 16KB (o 48KB en la serie Fermi) que se compartirá entre hilos del mismo bloque. Dado su tamaño y rapidez puede ser utilizada como caché.
  • Lecturas más rápidas de y hacia la GPU.
  • Soporte para enteros y operadores a nivel de bit.

Limitaciones

  • No se pueden utilizar variables estáticas dentro de funciones o funciones con número de parámetros variable.
  • No está soportado el renderizado de texturas.
  • En precisión simple no soporta números desnormalizados o NaNs.
  • Puede existir un cuello de botella entre la CPU y la GPU por los anchos de banda de los buses y sus latencias.
  • Por razones de eficiencia, los threads o hilos de ejecución deben lanzarse en grupos de al menos 32, con miles de hilos en total.

El modelo CUDA

CUDA intenta aprovechar el gran paralelismo, y el alto ancho de banda de la memoria en las GPU en aplicaciones con un gran coste aritmético frente a realizar numerosos accesos a memoria principal, lo que podría actuar de cuello de botella.

El modelo de programación de CUDA está diseñado para que se creen aplicaciones que de forma transparente escalen su paralelismo para poder incrementar el número de núcleos computacionales. Este diseño contiene tres puntos claves, que son la jerarquía de grupos de hilos, las memorias compartidas y las barreras de sincronización.

La estructura que se utiliza en este modelo está definido por un grid, dentro del cual hay bloques de hilos que están formados por como máximo 1024 hilos distintos.

Cada hilo en un bloque está identificado con un identificador único, que se accede con la variable threadIdx. Esta variable es muy útil para repartir el trabajo entre distintos hilos. threadIdx tiene 3 componentes (x, y, z), coincidiendo con las dimensiones de bloques de hilos. Así, cada elemento de una matriz, por ejemplo, lo podría tratar su homólogo en un bloque de hilos de dos dimensiones.

Al igual que los hilos, los bloques se identifican mediante blockIdx (en sus componentes x, y, z). Algunas otras funciones útiles son blockDim, para acceder al tamaño de bloque y gridDim, para acceder a la forma de la grid.

Kernel

Un kernel es el código que se ejecuta en el dispositivo, la función que ejecutan los diferentes flujos durante la fase paralela. En CUDA un kernel se ejecuta mediante un conjunto de flujos, es decir, es una función la cual al ejecutarse lo hará en N distintos hilos en lugar de en secuencial. Se define incluyendo __global__ en la declaración. Por ejemplo:

//Definición del kernel
__global__ void f(int a, int b, int c)
{
}

Si nuestra función f queremos que calcule la diferencia entre dos vectores A y B y lo almacene en un tercero C:

__global__ void f(int* A, int* B, int* C)
{
	int i = threadIdx.x;
	C[i] = A[i] - B[i];
}

Esta función se ejecutaría una vez en cada hilo, reduciendo el tiempo total de ejecución en gran medida, y dividiendo su complejidad, O(n), por una constante directamente relacionada con el número de procesadores disponibles.

El mismo ejemplo con matrices sería:

__global__ void f(int** A, int** B, int** C)
{
	int i = threadIdx.x; //Columna del bloque que ocupa este determinado hilo
	int j= threadIdx.y; //Fila
	C[i][j] = A[i][j] - B[i][j];
}

Cuando se lanza un kernel se crea una malla de hilos donde todos ellos ejecutan el mismo programa. El kernel especifica las instrucciones que van a ser ejecutadas por cada hilo individual y se pueden lanzar todos los hilos en un único bloque, lanzar varios bloques con un solo hilo cada uno, o lanzar varios bloques con varios hilos en cada bloque. De esta forma, el GPU se encarga de ejecutar simultáneamente tantas copias del kernel como hilos se tenga en ejecución. A cada hilo se le asignan sus propios datos de forma que cada copia realice la misma operación pero con datos diferentes, aprovechando así el paralelismo que ofrecen las GPUs.

Ejecución de un kernel

La memoria del procesador principal y del dispositivo son espacios de memoria completamente separados, lo que permite la computación simultánea tanto en la CPU como en la GPU sin competir por los recursos de memoria. Para ejecutar un kernel en el dispositivo GPU se siguen los siguientes pasos:

  1. Reservar memoria en el dispositivo
  2. Transferir los datos necesarios del procesador principal al espacio de memoria asignado al dispositivo.
  3. Invocar la ejecución del kernel en cuestión.
  4. Transferir los resultados del dispositivo al procesador principal y liberar la memoria del dispositivo una vez finalizada la ejecución del kernel.

Invocaciones a un kernel

En una llamada a un kernel, se le ha de pasar el tamaño de grid y de bloque, por ejemplo, en el main del ejemplo anterior podríamos añadir:

dim3 bloque(N,N); //Definimos un bloque de hilos de N*N
dim3 grid(M,M) //Grid de tamaño M*M

f<<<grid, bloque>>>(A, B, C);

En el momento que se invoque esta función, los bloques de un grid se enumerarán y distribuirán por los distintos multiprocesadores libres.

Sincronización

Como los distintos hilos colaboran entre ellos y pueden compartir datos, se requieren unas directivas de sincronización. En un kernel, se puede explicitar una barrera incluyendo una llamada a __syncthreads(), en la que todos los hilos se esperarán a que los demás lleguen a ese mismo punto.

Jerarquía de memoria

Los hilos en CUDA pueden acceder a distintas memorias, unas compartidas y otras no.

  • En primer lugar, está la memoria privada de cada hilo, solamente accesible desde él mismo.
  • Cada bloque de hilos posee también un espacio de memoria, compartida en este caso por los hilos del bloque y con un ámbito de vida igual que el del propio bloque.
  • Todos los hilos pueden acceder a una memoria global.

Además, existen otros dos espacios de memoria más, que son de solo lectura y accesibles por todos los hilos. Son la memoria constante y la de texturas. Todas las memorias de acceso global persisten mientras esté el kernel en ejecución.

Arquitectura CUDA

Un multiprocesador contiene ocho procesadores escalares, dos unidades especiales para funciones trascendentales, una unidad multihilo de instrucciones y una memoria compartida. El multiprocesador crea y maneja los hilos sin ningún tipo de overhead por la planificación, lo cual unido a una rápida sincronización por barreras y una creación de hilos muy ligera, consigue que se pueda utilizar CUDA en problemas de muy baja granularidad, incluso asignando un hilo a un elemento por ejemplo de una imagen (un píxel).

Tarjetas Soportadas

Lista completa, con la versión soportada de CUDA: https://developer.nvidia.com/cuda-gpus

Nvidia GeForce
GeForce RTX 3090
GeForce RTX 3080
GeForce RTX 3070
GeForce RTX TITAN
GeForce RTX 2080 SUPER
GeForce RTX 2080TI
GeForce RTX 2080
GeForce RTX 2070 SUPER
GeForce RTX 2070
GeForce RTX 2060 SUPER
GeForce RTX 2060
GeForce GTX 1660 SUPER
GeForce GTX 1660TI
GeForce GTX 1660
GeForce GTX 1650 SUPER
GeForce GTX 1650TI
GeForce GTX 1650
GeForce GTX TITAN V
GeForce GTX TITAN XP
GeForce GTX 1080Ti
GeForce GTX 1080
GeForce GTX 1070TI
GeForce GTX 1070
GeForce GTX 1060
GeForce GTX 1050Ti
GeForce GTX 1050
GeForce GTX TITAN X
GeForce GTX 980Ti
GeForce GTX 980
GeForce GTX 970
GeForce GTX 960
GeForce GTX 950
GeForce GTX TITAN Z
GeForce GTX TITAN
GeForce GTX 780Ti
GeForce GTX 780
GeForce GTX 770
GeForce GTX 760
GeForce GTX 750Ti
GeForce GTX 750
GeForce GTX 690
GeForce GTX 680
GeForce GTX 670
GeForce GTX 650
GeForce GT 640
GeForce GTX 590
GeForce GTX 580
GeForce GTX 570
GeForce GTX 560
GeForce GTX 550
GeForce GTX 480
GeForce GTX 470
GeForce GTX 465
GeForce GTX 460
GeForce GTS 450
GeForce GT 440
GeForce GT 430
GeForce GTX 295
GeForce GTX 285
GeForce GTX 280
GeForce GTX 275
GeForce GTX 260
GeForce GTS 250
GeForce GTS 240
GeForce GT 240
GeForce GT 220
GeForce 210/G210
GeForce 9800 GX2
GeForce 9800 GTX+
GeForce 9800 GTX
GeForce 9800 GT
GeForce 9600 GSO
GeForce 9600 GT
GeForce 9500 GT
GeForce 9400 GT
GeForce 9400 m
GeForce 9300 m
GeForce 9100 m
GeForce 8800 Ultra
GeForce 8800 GTX
GeForce 8800 GTS
GeForce 8800 GT
GeForce 8800 GS
GeForce 8600 GTS
GeForce 8600 GT
GeForce 8600 m
GeForce 8500 GT
GeForce 8400 GS
GeForce 8300 m
GeForce 8200 m
GeForce 8100 m
Nvidia GeForce Mobile GeForce RTX 2080 MaxQ
GeForce RTX 2070 MaxQ
GeForce RTX 2060 MaxQ
GeForce GTX 1660
GeForce GTX 1650
GeForce GTX 1080 MaxQ
GeForce GTX 1070 MaxQ
GeForce GTX 1060 MaxQ
GeForce GTX 1050 MaxQ
GeForce GTX 880M
GeForce GTX 780M
GeForce GTX 770M
GeForce GTX 765M
GeForce GTX 760M
GeForce GT 750M
GeForce GT 745M
GeForce GT 740M
GeForce GT 735M
GeForce GT 730M
GeForce GTX 680MX
GeForce GTX 680M
GeForce GTX 675MX
GeForce GTX 675M
GeForce GTX 670MX
GeForce GTX 670M
GeForce GTX 660M
GeForce GT 650M
GeForce GT 645M
GeForce GT 640M
GeForce GTX 580M
GeForce GTX 570M
GeForce GTX 560M
GeForce GT 555M
GeForce GT 550M
GeForce GT 540M
GeForce GT 525M
GeForce GT 520M
GeForce GTX 480M
GeForce GTX 285M
GeForce GTX 280M
GeForce GTX 260M
GeForce GTS 360M
GeForce GTS 350M
GeForce GTS 260M
GeForce GTS 250M
GeForce GT 620M
GeForce GT 335M
GeForce GT 330M
GeForce GT 325M
GeForce GT 320M
GeForce 310M
GeForce GT 240M
GeForce GT 230M
GeForce GT 220M
GeForce G210M
GeForce GTS 160M
GeForce GTS 150M
GeForce GT 130M
GeForce GT 120M
GeForce G110M
GeForce G105M
GeForce G103M
GeForce G102M
GeForce G100
GeForce 9800M GTX
GeForce 9800M GTS
GeForce 9800M GT
GeForce 9800M GS
GeForce 9700M GTS
GeForce 9700M GT
GeForce 9650M GT
GeForce 9650M GS
GeForce 9600M GT
GeForce 9600M GS
GeForce 9500M GS
GeForce 9500M G
GeForce 9400M G
GeForce 9300M GS
GeForce 9300M G
GeForce 9200M GS
GeForce 9100M G
GeForce 8800M GTX
GeForce 8800M GTS
GeForce 8700M GT
GeForce 8600M GT
GeForce 8600M GS
GeForce 8400M GT
GeForce 8400M GS
GeForce 8400M G
GeForce 8200M G
Nvidia Quadro
Quadro RTX 8000
Quadro RTX 6000
Quadro RTX 5000
Quadro RTX 4000
Quadro GP100
Quadro GV100
Quadro P6000
Quadro P5000
Quadro P4000
Quadro P2200
Quadro P2000
Quadro P1000
Quadro P620
Quadro P600
Quadro 6000
Quadro 5000
Quadro 4000
Quadro FX 5800
Quadro FX 5600
Quadro FX 4800
Quadro FX 4700 X2
Quadro FX 4600
Quadro FX 3800
Quadro FX 3700
Quadro FX 1800
Quadro FX 1700
Quadro FX 580
Quadro FX 570
Quadro FX 380
Quadro FX 370
Quadro NVS 450
Quadro NVS 420
Quadro NVS 295
Quadro NVS 290
Quadro Plex 1000 Model IV
Quadro Plex 1000 Model S4
Nvidia Quadro Mobile
Quadro FX 3800M
Quadro FX 3700M
Quadro FX 3600M
Quadro FX 2800M
Quadro FX 2700M
Quadro FX 1800M
Quadro FX 1700M
Quadro FX 1600M
Quadro FX 880M
Quadro FX 770M
Quadro FX 570M
Quadro FX 380M
Quadro FX 370M
Quadro FX 360M
Quadro NVS 320M
Quadro NVS 160M
Quadro NVS 150M
Quadro NVS 140M
Quadro NVS 135M
Quadro NVS 130M
Nvidia Tesla
Tesla C2050
Tesla S1070
Tesla M1060
Tesla C1060
Tesla C870
Tesla D870
Tesla S870

IDEs

Visual Studio: CUDA proporciona un pequeño conjunto de extensiones para lenguajes de programación estándar, como C, que permiten una implementación sencilla de algoritmos paralelos. Con CUDA C/C++, los programadores pueden concentrarse en la tarea de paralelizar los algoritmos en lugar de dedicar tiempo a su implementación.

Para usar CUDA en su sistema, necesitará lo siguiente instalado:

  • Una GPU compatible con CUDA
  • Una versión compatible de Microsoft Windows
  • Una versión compatible de Microsoft Visual
  • Studio (2015, 2017, 2019, 2022)
  • El kit de herramientas NVIDIA CUDA[7]

Campos de utilización

Los campos de utilización de CUDA son muy variados y van en aumento con el paso del tiempo. Entre los más populares se encuentran:

  • Animación y modelado:

El motor gráfico Unreal Engine de Epic Games utiliza una GPU única y un único nodo. Usa CUDA para hacer un renderizado acelerado por GPU en OpenGL, DirectX y Vulkan. También para implementar Phys-X.

  • Astronomía y Astrofísica:

La GPU-AH de Universidade do Porto utiliza una GPU única y un nodo único. Usa CUDA para calcular la densidad y la velocidad promedio de la red.

  • Big Data y minería de datos:

La ADVANCE.AI utiliza multi GPU y multi nodos. Usa CUDA para el reconocimiento de documentos de identidad, incorporación digital de clientes, eliminar el fraude/robo de identidad y la verificación de identidad sin contacto. También los servicios de pagos vinculados.

  • Bioinformática:

El DEEPCHAIN de InstaDeep Ltd. usa multi GPU pero un nodo único. Implementa CUDA para calcular la probabilidad de transición de cualquier mutación utilizando modelos de lenguaje de última generación, experimentos de mutagénesis in-silico a partir de archivos PDB de proteínas, simulaciones de dinámica molecular a gran escala y visualizaciones 3D.

  • Modelado climático, meteorológico y oceánico:

COSMO de COSMO consortium utiliza multi GPU y multi nodos. Usan CUDA para todas las funciones en la rama MCH utilizadas para el pronóstico del tiempo operativo.[6]

Referencias

  1. «Productos aptos para CUDA - NVIDIA».
  2. «Parallel Thread Execution ISA Version 7.4». docs.nvidia.com (en inglés estadounidense). Consultado el 7 de agosto de 2021.
  3. «CUDA Installation Guide for Microsoft Windows». docs.nvidia.com (en inglés estadounidense). Consultado el 9 de junio de 2019.
  4. «NVIDIA CUDA Installation Guide for Linux». docs.nvidia.com (en inglés estadounidense). Consultado el 9 de junio de 2019.
  5. «NVIDIA CUDA Installation Guide for Mac OS X». docs.nvidia.com (en inglés estadounidense). Consultado el 9 de junio de 2019.
  6. «CUDA Zone - Library of Resources». NVIDIA Developer (en inglés). 18 de julio de 2017. Consultado el 2 de junio de 2022.
  7. «CUDA Installation Guide for Microsoft Windows». docs.nvidia.com (en inglés estadounidense). Consultado el 2 de junio de 2022.
  • Sanders, Jason. (2016). CUDA by Example: An Introduction to General-Purpose GPU Programming. 2a ed. Upper Saddle River, New Jersey : Addison-Wesley.
  • Iván Rivera; M. Vargas-Lombardo. (Diciembre de 2012). Principios y Campos de Aplicación en CUDA Programación paralela y sus potencialidades. Nexo. Revista Científica, 25, 39-46.
  • Francesc Guim, Ivan Rodero. (2015). Arquitecturas basadas en computación gráfica (GPU). Recuperado el 15/11/2019, de Universitat Oberta de Catalunya Sitio web: https://www.exabyteinformatica.com/uoc/Informatica/Arquitecturas-de-computadores-avanzadas/Arquitecturas-de-computadores-avanzadas-(Modulo-5).pdf
  • Misael Angeles Arce, Georgina Flores Becerra, and Antonio M. Vidal. (2016). Implementación CPU-GPU y comparativa de las bibliotecasBLAS-CUBLAS, LAPACK-CULA.. Recuperado el 15/11/2019, de Universidad Politécnica de Valencia Sitio web: https://riunet.upv.es/bitstream/handle/10251/11735/INCO2-2011-01.pdf
  • César Represa Pérez José María Cámara Nebreda Pedro Luis Sánchez Ortega . (2016). UNIVERSIDAD DE BURGOS Área de Tecnología Electrónica INTRODUCCIÓN A LA PROGRAMACIÓN EN CUDA. Recuperado el 15/11/2019, de UNIVERSIDAD DE BURGOS Sitio web: https://riubu.ubu.es/bitstream/handle/10259/3933/Programacion-en-CUDA.pdf;jsessionid=4F61BF7B394035CC9E8553901D643C16?sequence=1

Véase también

Enlaces externos

Este artículo ha sido escrito por Wikipedia. El texto está disponible bajo la licencia Creative Commons - Atribución - CompartirIgual. Pueden aplicarse cláusulas adicionales a los archivos multimedia.