¿Qué es CUDA? Programación paralela para GPU

CUDA es una plataforma de computación paralela y un modelo de programación desarrollado por Nvidia para computación general en sus propias GPU (unidades de procesamiento de gráficos). CUDA permite a los desarrolladores acelerar las aplicaciones de computación intensiva al aprovechar la potencia de las GPU para la parte paralelizable de la computación.

Si bien se han propuesto otras API para GPU, como OpenCL, y hay GPU competitivas de otras empresas, como AMD, la combinación de GPU CUDA y Nvidia domina varias áreas de aplicación, incluido el aprendizaje profundo, y es la base de algunas de las las computadoras más rápidas del mundo.

Podría decirse que las tarjetas gráficas son tan antiguas como la PC, es decir, si considera que el Adaptador de pantalla monocromática IBM 1981 es una tarjeta gráfica. En 1988, podía obtener una tarjeta Wonder VGA 2D de 16 bits de ATI (la empresa finalmente adquirida por AMD). En 1996, se podía comprar un acelerador de gráficos 3D de 3dfx Interactive para poder ejecutar el juego de disparos en primera persona Quake a toda velocidad.

También en 1996, Nvidia comenzó a intentar competir en el mercado de aceleradores 3D con productos débiles, pero aprendió sobre la marcha y en 1999 presentó la exitosa GeForce 256, la primera tarjeta gráfica que se denominó GPU. En ese momento, la razón principal para tener una GPU era para jugar. No fue hasta más tarde que la gente usó GPU para matemáticas, ciencias e ingeniería.

El origen de CUDA

En 2003, un equipo de investigadores dirigido por Ian Buck dio a conocer Brook, el primer modelo de programación ampliamente adoptado para extender C con construcciones paralelas de datos. Más tarde, Buck se unió a Nvidia y lideró el lanzamiento de CUDA en 2006, la primera solución comercial para computación de propósito general en GPU.

OpenCL frente a CUDA

El competidor de CUDA OpenCL fue lanzado por Apple y el Grupo Khronos en 2009, en un intento de proporcionar un estándar para la computación heterogénea que no se limitara a las CPU Intel / AMD con GPU Nvidia. Si bien OpenCL suena atractivo debido a su generalidad, no ha funcionado tan bien como CUDA en las GPU de Nvidia, y muchos marcos de aprendizaje profundo no lo admiten o lo admiten solo como una ocurrencia tardía una vez que se ha lanzado su compatibilidad con CUDA.

Aumento del rendimiento de CUDA

CUDA ha mejorado y ampliado su alcance a lo largo de los años, más o menos al mismo ritmo que las GPU Nvidia mejoradas. A partir de la versión 9.2 de CUDA, al utilizar varias GPU de servidor P100, puede realizar mejoras de rendimiento hasta 50 veces superiores a las de las CPU. El V100 (no mostrado en esta figura) es 3 veces más rápido para algunas cargas. La generación anterior de GPU de servidor, la K80, ofrecía mejoras de rendimiento de 5 a 12 veces superiores a las CPU.

Nvidia

El aumento de velocidad de las GPU ha llegado justo a tiempo para la informática de alto rendimiento. El aumento del rendimiento de un solo subproceso de las CPU a lo largo del tiempo, que según la ley de Moore se duplicaría cada 18 meses, se ha ralentizado hasta un 10 por ciento por año a medida que los fabricantes de chips encontraron límites físicos, incluidos límites de tamaño en la resolución de la máscara de chip y el rendimiento del chip durante el proceso de fabricación y límites de calor en las frecuencias de reloj en tiempo de ejecución.

Nvidia

Dominios de aplicación CUDA

Nvidia

Las GPU CUDA y Nvidia se han adoptado en muchas áreas que necesitan un alto rendimiento informático de punto flotante, como se resume gráficamente en la imagen de arriba. Una lista más completa incluye:

  1. Finanzas computacionales
  2. Modelización del clima, el tiempo y los océanos
  3. Ciencia y análisis de datos
  4. Aprendizaje profundo y aprendizaje automático
  5. Defensa e inteligencia
  6. Fabricación / AEC (Arquitectura, Ingeniería y Construcción): CAD y CAE (incluida la dinámica de fluidos computacional, la mecánica estructural computacional, el diseño y la visualización y la automatización del diseño electrónico)
  7. Medios y entretenimiento (incluyendo animación, modelado y renderizado; corrección de color y manejo de granulado; composición; acabado y efectos; edición; codificación y distribución digital; gráficos en el aire; herramientas en el set, revisión y estéreo; y gráficos meteorológicos)
  8. Imagenes medicas
  9. Petróleo y gas
  10. Investigación: Educación superior y supercomputación (incluida la química y biología computacional, el análisis numérico, la física y la visualización científica)
  11. Seguridad y proteccion
  12. Herramientas y gestión

CUDA en aprendizaje profundo

El aprendizaje profundo tiene una enorme necesidad de velocidad informática. Por ejemplo, para entrenar los modelos para Google Translate en 2016, los equipos de Google Brain y Google Translate realizaron cientos de ejecuciones de TensorFlow de una semana usando GPU; habían comprado 2000 GPU de nivel de servidor de Nvidia para este propósito. Sin GPU, esas ejecuciones de entrenamiento habrían tardado meses en converger en lugar de una semana. Para la implementación de producción de esos modelos de traducción de TensorFlow, Google usó un nuevo chip de procesamiento personalizado, la TPU (unidad de procesamiento de tensor).

Además de TensorFlow, muchos otros marcos de DL dependen de CUDA para su compatibilidad con GPU, incluidos Caffe2, CNTK, Databricks, H2O.ai, Keras, MXNet, PyTorch, Theano y Torch. En la mayoría de los casos, utilizan la biblioteca cuDNN para los cálculos de redes neuronales profundas. Esa biblioteca es tan importante para el entrenamiento de los marcos de aprendizaje profundo que todos los marcos que utilizan una versión determinada de cuDNN tienen esencialmente los mismos números de rendimiento para casos de uso equivalentes. Cuando CUDA y cuDNN mejoran de una versión a otra, todos los marcos de aprendizaje profundo que se actualizan a la nueva versión ven las ganancias de rendimiento. Donde el rendimiento tiende a diferir de un marco a otro es en qué tan bien escalan a múltiples GPU y múltiples nodos.

Programación CUDA

Nvidia

Kit de herramientas CUDA

El kit de herramientas CUDA incluye bibliotecas, herramientas de depuración y optimización, un compilador, documentación y una biblioteca en tiempo de ejecución para implementar sus aplicaciones. Tiene componentes que admiten aprendizaje profundo, álgebra lineal, procesamiento de señales y algoritmos paralelos. En general, las bibliotecas CUDA admiten todas las familias de GPU de Nvidia, pero funcionan mejor en la última generación, como la V100, que puede ser 3 veces más rápida que la P100 para cargas de trabajo de entrenamiento de aprendizaje profundo. El uso de una o más bibliotecas es la forma más fácil de aprovechar las GPU, siempre que los algoritmos necesarios se hayan implementado en la biblioteca adecuada.

Nvidia

Bibliotecas de aprendizaje profundo CUDA

En la esfera del aprendizaje profundo, hay tres bibliotecas principales aceleradas por GPU: cuDNN, que mencioné anteriormente como el componente de GPU para la mayoría de los marcos de aprendizaje profundo de código abierto; TensorRT, que es el optimizador y el tiempo de ejecución de inferencia de aprendizaje profundo de alto rendimiento de Nvidia; y DeepStream, una biblioteca de inferencias de video. TensorRT lo ayuda a optimizar los modelos de redes neuronales, calibrar para obtener una precisión más baja con alta precisión e implementar los modelos entrenados en nubes, centros de datos, sistemas integrados o plataformas de productos automotrices.

Nvidia

Bibliotecas de álgebra lineal y matemáticas CUDA

El álgebra lineal sustenta los cálculos de tensores y, por lo tanto, el aprendizaje profundo. BLAS (subprogramas de álgebra lineal básica), una colección de algoritmos matriciales implementados en Fortran en 1989, ha sido utilizado desde entonces por científicos e ingenieros. cuBLAS es una versión de BLAS acelerada por GPU y la forma de mayor rendimiento de hacer aritmética matricial con GPU. cuBLAS asume que las matrices son densas; cuSPARSE maneja matrices dispersas.

Nvidia

Bibliotecas de procesamiento de señales CUDA

La transformada rápida de Fourier (FFT) es uno de los algoritmos básicos utilizados para el procesamiento de señales; convierte una señal (como una forma de onda de audio) en un espectro de frecuencias. cuFFT es una FFT acelerada por GPU.

Los códecs, que utilizan estándares como H.264, codifican / comprimen y decodifican / descomprimen video para su transmisión y visualización. Nvidia Video Codec SDK acelera este proceso con GPU.

Nvidia

Bibliotecas de algoritmos paralelos CUDA

Las tres bibliotecas para algoritmos paralelos tienen diferentes propósitos. NCCL (Biblioteca de comunicaciones colectivas de Nvidia) es para escalar aplicaciones en múltiples GPU y nodos; nvGRAPH es para análisis de gráficos paralelos; y Thrust es una biblioteca de plantillas de C ++ para CUDA basada en la biblioteca de plantillas estándar de C ++. Thrust proporciona una rica colección de primitivas paralelas de datos como escanear, ordenar y reducir.

Nvidia

CUDA frente al rendimiento de la CPU

En algunos casos, puede utilizar funciones CUDA integradas en lugar de las funciones de CPU equivalentes. Por ejemplo, las rutinas de multiplicación de matrices GEMM de BLAS se pueden reemplazar por versiones de GPU simplemente vinculando a la biblioteca NVBLAS:

Nvidia

Conceptos básicos de programación CUDA

Si no puede encontrar las rutinas de la biblioteca CUDA para acelerar sus programas, tendrá que probar suerte con la programación CUDA de bajo nivel. Eso es mucho más fácil ahora que cuando lo probé por primera vez a fines de la década de 2000. Entre otras razones, hay una sintaxis más sencilla y mejores herramientas de desarrollo disponibles. Mi única objeción es que en MacOS, el último compilador de CUDA y el último compilador de C ++ (de Xcode) rara vez están sincronizados. Uno tiene que descargar herramientas de línea de comandos más antiguas de Apple y cambiar a ellas usando xcode-selectpara obtener el código CUDA para compilar y vincular.

Por ejemplo, considere esta sencilla rutina de C / C ++ para agregar dos matrices:

añadir vacío (int n, float * x, float * y)

{  

       para (int i = 0; i <n; i ++)      

             y [i] = x [i] + y [i];

}

Puede convertirlo en un kernel que se ejecutará en la GPU agregando la __global__palabra clave a la declaración y llamar al kernel usando la sintaxis de corchetes triples:

agregar << >> (N, x, y);

También tiene que cambiar sus malloc/ newy free/ deletellamadas a cudaMallocManagedy cudaFreepor lo que se están asignando espacio en la GPU. Finalmente, debe esperar a que se complete un cálculo de GPU antes de usar los resultados en la CPU, lo que puede lograr con cudaDeviceSynchronize.

El soporte triple anterior usa un bloque de hilo y un hilo. Las GPU actuales de Nvidia pueden manejar muchos bloques e hilos. Por ejemplo, una GPU Tesla P100 basada en la arquitectura de GPU Pascal tiene 56 multiprocesadores de transmisión (SM), cada uno capaz de admitir hasta 2048 subprocesos activos.

El código del kernel necesitará conocer su bloque e índice de hilo para encontrar su desplazamiento en las matrices pasadas. El kernel paralelizado a menudo usa un bucle de cuadrícula , como el siguiente:

__global__

añadir vacío (int n, float * x, float * y)

{

   int índice = blockIdx.x * blockDim.x + threadIdx.x;

   int stride = blockDim.x * gridDim.x;

   para (int i = índice; i <n; i + = zancada)

     y [i] = x [i] + y [i];

}

Si observa las muestras en el kit de herramientas de CUDA, verá que hay más que considerar que los conceptos básicos que cubrí anteriormente. Por ejemplo, algunas llamadas a funciones CUDA deben incluirse en checkCudaErrors()llamadas. Además, en muchos casos, el código más rápido utilizará bibliotecas como, cuBLASpor ejemplo, junto con asignaciones de memoria de dispositivo y host y copia de matrices de un lado a otro.

En resumen, puede acelerar sus aplicaciones con GPU en muchos niveles. Puede escribir código CUDA; puede llamar a las bibliotecas CUDA; y puede utilizar aplicaciones que ya sean compatibles con CUDA.