Revisión: Rapids de Nvidia lleva el análisis de Python a la GPU

La creación de modelos de aprendizaje automático es un proceso repetitivo. A menudo de memoria y de rutina, este es un juego de “el más rápido en el ciclo gana”, ya que cuanto más rápido pueda iterar, más fácil será explorar nuevas teorías y obtener buenas respuestas. Esta es una de las razones por las que el uso empresarial práctico de la IA en la actualidad está dominado por las empresas más grandes, que pueden aportar enormes recursos al problema.

Rapids es un paraguas para varios proyectos de código abierto, incubados por Nvidia, que coloca toda la línea de procesamiento en la GPU, eliminando las transferencias de datos vinculadas de E / S, al tiempo que aumenta sustancialmente la velocidad de cada uno de los pasos individuales. También proporciona un formato común para los datos, lo que alivia la carga de intercambiar datos entre sistemas dispares. A nivel de usuario, Rapids imita la API de Python para facilitar la transición para esa base de usuarios.

El libro de cocina de Tidyverse

Arquitectura del ecosistema de Rapids

El proyecto Rapids tiene como objetivo replicar, en su mayor parte, las API de análisis de datos y aprendizaje automático de Python, pero para GPU en lugar de CPU. Esto significa que los desarrolladores de Python ya tienen todo lo que necesitan para ejecutar en la GPU, sin tener que aprender los detalles de bajo nivel de la programación CUDA y las operaciones paralelas. Los Pythonistas pueden desarrollar código en una máquina no habilitada para GPU y luego, con algunos ajustes, ejecutarlo en todas las GPU disponibles para ellos.

El kit de herramientas de Nvidia CUDA proporciona primitivas de nivel inferior para bibliotecas matemáticas, algoritmos paralelos y análisis de gráficos. En el corazón de la arquitectura se encuentra el marco de datos de la GPU, basado en Apache Arrow, que proporciona una estructura de datos en memoria en columnas que es independiente del lenguaje de programación. El usuario interactúa con el marco de datos de la GPU a través de cuDF y una API similar a Pandas. Dask, una biblioteca de Python para computación paralela, imita las API de Python ascendentes y trabaja con bibliotecas CUDA para computación en paralelo. Piense en Dask como Spark para Python.

RÁPIDOS

Los tres proyectos principales, cuDF, cuML y cuGraph, se desarrollan de forma independiente, pero están diseñados para funcionar juntos sin problemas. También se están desarrollando puentes hacia el ecosistema más amplio de Python como parte del proyecto.

Instalación rápida

La instalación a través de Anaconda en una máquina Linux en AWS fue en su mayor parte sencilla, salvo algunos contratiempos debido a un cambio en las dependencias en la versión 0.11. Instalar las bibliotecas C / C ++ para usar libcudf no fue tan fácil, y recomiendo ceñirse a las API de Python y al proceso de instalación de Conda. Rapids incluye un cuaderno Jupyter, también disponible en Colab gratuito de Google, que hace que comenzar sea simple. Usé la versión 0.10 del portátil Jupyter para ejecutar el código en Google Colab, que incluye una GPU Nvidia Tesla T4.

Marco de datos de GPU de Rapids

En el corazón de cualquier flujo de trabajo de ciencia de datos se encuentra el marco de datos. Aquí es donde ocurre la ingeniería de características y donde se pasa la mayor parte del tiempo, mientras los científicos de datos disputan datos sucios. cuDF es el proyecto Rapids para un marco de datos similar a Pandas basado en GPU. El soporte de cuDF es libcudf, una biblioteca de C ++ que implementa primitivas de bajo nivel para importar datos de Apache Arrow, realizar matemáticas de elementos en matrices y ejecutar operaciones de ordenación, unión, agrupación, reducción y otras en matrices de memoria en GPU. La estructura de datos básica de libcudf es el GPU DataFrame (GDF), que a su vez se modela en el almacén de datos en columnas de Apache Arrow.

RÁPIDOS

La biblioteca Rapids Python presenta al usuario una interfaz de nivel superior que se asemeja a los marcos de datos, como los de Pandas. En muchos casos, el código de Pandas se ejecuta sin cambios en cuDF. Cuando este no es el caso, normalmente solo se requieren cambios menores.

Funciones definidas por el usuario en cuDF

Una vez que haya pasado la manipulación básica de datos, a veces es necesario procesar filas y columnas con funciones definidas por el usuario (UDF). cuDF proporciona una API de estilo PyData para escribir código para procesar estructuras de datos más detalladas como matrices, series y ventanas móviles. Actualmente, solo se admiten los tipos numéricos y booleanos. Las UDF se compilan utilizando el compilador Numba JIT, que utiliza un subconjunto de LLVM para compilar funciones numéricas en el código de máquina CUDA. Esto da como resultado tiempos de ejecución sustancialmente más rápidos en la GPU.

Cuerdas en cuDF

Aunque las GPU son fantásticas para procesar rápidamente vectores flotantes, normalmente no se han utilizado para procesar datos de cadenas, y la realidad es que la mayoría de los datos nos llegan en forma de cadenas. cuStrings es una biblioteca de manipulación de cadenas de GPU para dividir, aplicar expresiones regulares, concatenar, reemplazar tokens, etc. en matrices de cadenas. Al igual que otras funciones de cuDF, se implementa como una biblioteca C / C ++ (libnvStrings) y está envuelto por una capa de Python diseñada para imitar a Pandas. Aunque el tipo de datos de cadena no está optimizado para su ejecución en GPU, la ejecución paralela del código debería proporcionar una aceleración sobre la manipulación de cadenas basada en CPU.

Obtener datos dentro o fuera de cuDF

La E / S del marco de datos es manejada por una biblioteca dedicada, cuIO. Se admiten todos los formatos más comunes, incluidos Arrow, ORC, Parquet, HDF5 y CSV. Si tiene la suerte de ejecutar el hardware DGX-2, puede usar la integración de almacenamiento directo de GPU para mover datos directamente desde el almacenamiento de alta velocidad a la GPU sin involucrar a la CPU. Los usuarios mortales aún apreciarán la aceleración que brinda la GPU al descomprimir grandes conjuntos de datos y la estrecha integración con el ecosistema de Python.

El almacenamiento directo de GPU se encuentra actualmente en alfa y, cuando se lance, estará disponible en la mayoría de las GPU de Tesla. Puede crear un marco de datos de GPU a partir de matrices NumPy, Pandas DataFrames y tablas PyArrow con una sola línea de código. Otros proyectos pueden intercambiar datos a través de las __cuda_array_interface__bibliotecas que se encuentran dentro del ecosistema Numba. DLPack para bibliotecas de redes neuronales también es una interfaz compatible.

Probablemente el mayor inconveniente de usar cuDF es la falta de interoperabilidad fuera de Python. Creo que un enfoque en una base sólida de API de C / C ++, como lo ha hecho Arrow, permitiría un ecosistema más amplio y beneficiaría al proyecto en su conjunto.

CuML de Rapids

Los objetivos declarados de cuML son ser "Scikit-learn de Python con tecnología de GPU". En teoría, esto significa que solo debería tener que cambiar su declaración de importación y quizás ajustar algunos de los parámetros para tener en cuenta las diferencias en la ejecución en una CPU, donde a veces es mejor un enfoque de fuerza bruta. El beneficio de tener un Scikit-learn basado en GPU es difícil de subestimar. Las aceleraciones son sustanciales y los analistas de datos pueden ser mucho más productivos. La API de C ++ no está lista para un amplio consumo fuera de sus enlaces de Python, pero se espera que esto mejore.

cuML también incluye API para ayudar con el ajuste de hiperparámetros a través de Dask, una biblioteca para escalar Python en múltiples nodos. Muchos algoritmos de aprendizaje automático se pueden hacer en paralelo de manera efectiva, y cuML está desarrollando activamente algoritmos de múltiples GPU y múltiples nodos y múltiples GPU.

RÁPIDOS

Gráfico de Rapids

cuGraph es el tercer miembro del ecosistema Rapids y, como los demás, cuGraph está completamente integrado con cuDF y cuML. Ofrece una buena selección de algoritmos de gráficos, primitivas y utilidades, todos con rendimiento acelerado por GPU. La selección de API en cuGraph es algo más extensa que en otras partes de Rapids, con NetworkX, Pregel, GraphBLAS y GQL (Graph Query Language) disponibles.

RÁPIDOS

cuGraph es más como un juego de herramientas en espíritu que cuML. La tecnología gráfica es un espacio en rápido movimiento tanto en la academia como en la industria. Por lo tanto, por diseño, cuGraph brinda a los desarrolladores acceso a la capa C ++ y las primitivas de gráficos, lo que alienta a terceros a desarrollar productos utilizando cuGraph. Varias universidades han contribuido, y proyectos de Texas A&M (GraphBLAS), Georgia Tech (Hornet) y UC Davis (Gunrock) se han “producido” e incluido bajo el paraguas de cuGraph. Cada proyecto proporciona un conjunto diferente de capacidades, todas aceleradas por GPU y todas respaldadas por el mismo marco de datos cuDF.

NetworkX es la API de Python destinada por el equipo de Rapids para su interfaz nativa. Hay varios algoritmos disponibles a través de esa interfaz. Si bien solo el rango de página es multi-GPU, el equipo está trabajando activamente en versiones multi-GPU de los demás, cuando corresponda.

RÁPIDOS

Uno de los subproyectos de cuGraph que encontré interesante es cugraphBLAS, un esfuerzo por estandarizar los bloques de construcción para algoritmos de gráficos en el lenguaje del álgebra lineal. Basado en GraphBLAS (graphblas.org), una estructura de datos personalizada diseñada para el procesamiento de gráficos dinámicos dispersos.

Otro subproyecto de cuGraph, Hornet proporciona un formato independiente del sistema para contener datos de gráficos, análogo a la forma en que Apache arrow proporciona una forma independiente del sistema para procesar marcos de datos. Hornet es compatible con la mayoría de los formatos de gráficos populares, incluidos SNAP, mtx, metis y bordes.

De acuerdo con el espíritu de estar cerca de la comunidad de Python, el paquete nativo NetworkX de Python se puede utilizar para el estudio de redes complejas. Esto incluye estructuras de datos para gráficos y gráficos múltiples, reimplementados utilizando primitivas CUDA, lo que le permite reutilizar muchos de los algoritmos de gráficos estándar y realizar medidas de análisis y estructura de red. La mayoría de los algoritmos son de una sola GPU, como NetworkX. Sin embargo, ejecutarlos solo en la GPU ofrece una aceleración significativa, mientras que el trabajo continúa avanzando hacia implementaciones de múltiples GPU.

En la hoja de ruta de Rapids 

Dada la tremenda velocidad que proporciona el análisis basado en GPU, hay algunos proyectos nuevos que se incorporarán a la mezcla en versiones futuras.

DLPack y array_interface para aprendizaje profundo

Las redes neuronales multicapa fueron una de las primeras cargas de trabajo que se trasladaron a las GPU, y existe una gran cantidad de código para este caso de uso de aprendizaje automático. Anteriormente, DLPack era el estándar de facto para el intercambio de datos entre bibliotecas de aprendizaje profundo. Hoy en día, el array_interface es comúnmente compatible. Rapids es compatible con ambos.

cuSignal

Como la mayoría de los otros proyectos en Rapids, cuSignal es una versión acelerada por GPU de una biblioteca Python existente, en este caso la biblioteca SciPy Signal. La biblioteca SciPy Signal original se basa en NumPy, que se reemplaza con su equivalente acelerado por GPU, CuPy en cuSignal. Este es un buen ejemplo de la filosofía de diseño de Rapids en funcionamiento. Con la excepción de algunos kernels CUDA personalizados, el puerto a la GPU implica principalmente reemplazar la declaración de importación y ajustar algunos parámetros de función. 

Llevar el procesamiento de señales al pliegue de Rapids es un movimiento inteligente. El procesamiento de señales está en todas partes y tiene muchas aplicaciones comerciales de utilidad inmediata en la industria y la defensa.

cuSpatial

Las operaciones espaciales y espacio-temporales son excelentes candidatos para la aceleración de la GPU y resuelven muchos problemas del mundo real que enfrentamos en la vida cotidiana, como el análisis de patrones de tráfico, la salud / calidad del suelo y el riesgo de inundaciones. Gran parte de los datos recopilados por los dispositivos móviles, incluidos los drones, tienen un componente geoespacial y el análisis espacial está en el corazón de Smart City. 

Con la arquitectura de los otros componentes, cuSpatial es una biblioteca C ++ construida sobre primitivas CUDA y la biblioteca de procesamiento vectorial Thrust, que usa cuDF para el intercambio de datos. Los consumidores de la biblioteca C ++ pueden leer datos de puntos, polilíneas y polígonos con un lector de C ++. Los usuarios de Python están mejor si usan paquetes de Python existentes como Shapely o Fiona para llenar una matriz NumPy, luego usan la API cuSpatial Python o convierten a marcos de datos cuDF. 

cuxfilter para visualización de datos

La visualización de datos es fundamental, tanto dentro del flujo de trabajo de análisis como para presentar o informar resultados. Sin embargo, a pesar de toda la magia de que las GPU pueden trabajar con los datos en sí, enviar esos datos a un navegador no es una tarea trivial. cuxfilter, inspirado en la biblioteca de JavaScript Crossfilter, tiene como objetivo cerrar esa brecha al proporcionar una pila para permitir que las bibliotecas de visualización de terceros muestren datos en marcos de datos cuDF.

Ha habido algunas iteraciones de cuxfilter a medida que el equipo clasifica la mejor arquitectura y patrones de conectores. La última versión aprovecha los portátiles Jupyter, el servidor Bokeh y los paneles PyViz, mientras que los experimentos de integración incluyen proyectos de Uber, Falcon y PyDeck. Este componente aún no está listo para el horario de máxima audiencia, pero está programado para su lanzamiento en Rapids 0.13. Hay muchas partes móviles y no pude experimentar con ellas de primera mano, pero si cumple con su promesa, será una gran adición al conjunto de herramientas de Rapids.

Ampliando y ampliando con Dask

Dask es un programador de tareas distribuido para Python, que desempeña un papel similar para Python que Apache Spark para Scala. Dask-cuDF es una biblioteca que proporciona marcos de datos particionados respaldados por GPU. Dask-cuDF funciona bien cuando planea usar cuML o cuando está cargando un conjunto de datos que es más grande que la memoria de la GPU o está distribuido en varios archivos.

Al igual que un Spark RDD (conjunto de datos distribuido resistente), el marco de datos distribuido Dask-cuDF se comporta principalmente como uno local, por lo que puede experimentar con su máquina local y pasar a un modelo distribuido cuando necesite escalar. Dask-cuML brinda capacidades de múltiples nodos cuML, lo que lo convierte en una buena opción cuando no tiene el presupuesto para una estación de trabajo DGX.