RAPIDS es un conjunto de bibliotecas de inteligencia artificial y ciencia de datos aceleradas por GPU de código abierto que cuentan con un buen soporte para la escalabilidad con motores distribuidos como Spark y Dask .
Ray es un popular marco de Python distribuido de código abierto que se usa comúnmente para escalar aplicaciones de inteligencia artificial y aprendizaje automático (ML). Ray se destaca particularmente en la simplificación y escalabilidad de los procesos de entrenamiento e inferencia y puede apuntar fácilmente a dispositivos tanto de CPU como de GPU.
En esta publicación, exploramos cómo se pueden usar Ray y RAPIDS para acelerar nuevos procesos de análisis.
Actores de Ray
Si bien Ray ofrece abstracciones de alto nivel para entrenar y ofrecer modelos de ML, experimentaremos con el núcleo de Ray , específicamente con los actores de Ray . Los actores son trabajadores con estado, lo que significa que cada trabajador puede almacenar, administrar y modificar cualquier dato almacenado. Por ejemplo, si desea utilizar cuDF para cargar algunos datos en la GPU, puede hacer lo siguiente:
@ray .remote(num_gpus = 1 ) class cuDFActor: def __init__( self ): ... def read_parquet( self , filepath: str , columns: list = None ) - > cudf.DataFrame: return cudf.read_parquet(filepath, columns = columns) # Start 4 Workers pool_size = 4 actor_pool = [cuDFActor.remote() for i in range (pool_size)] |
Este ejemplo utiliza Ray para crear cuatro actores en cuatro GPU y cuDF para acelerar la entrada y salida. Este ejemplo se puede utilizar con otras optimizaciones de RAPIDS (configuración de memoria con RMM) o rutinas ETL comunes como funciones de filtrado/personalizadas y definidas por el usuario: ejemplo de cudf ray-actor .
Los actores Ray son increíblemente generales y se pueden aprovechar rápidamente para paralelizar bibliotecas de Python y también se pueden integrar fácilmente con algoritmos distribuidos existentes. Además, con Ray, puedes escalar fácilmente este trabajo en múltiples GPU y múltiples nodos.
NCCL y cuGraph
Ya se han creado muchas implementaciones de algoritmos populares de RAPIDS para computación acelerada distribuida en GPU en C++. Estas implementaciones están altamente optimizadas y se basan en comunicaciones aceleradas con NCCL y primitivas y solucionadores que se encuentran en RAFT (distancias por pares, agrupamiento de k-medias, solucionadores iterativos y más). Las primitivas de RAFT se utilizan en varias bibliotecas de RAPIDS, incluidas cuML y cuGraph.
Por ejemplo, la implementación de componentes débilmente conectados (WCC) de cuGraph se basa en gran medida en la canalización de datos ya limpios lo más rápido posible desde el disco a la implementación de CUDA C++ de nivel inferior. WCC es un buen objetivo para demostrar cómo los desarrolladores pueden usar RAPIDS (cuGraph) y Ray juntos para obtener acceso a algoritmos potentes, distribuidos y acelerados.
Para implementar el CMI se requiere lo siguiente:
- Cargando datos en la memoria de la GPU
- Iniciando comunicaciones NCCL (y subcomunicador cuGraph)
- Creación de instancias y configuración de la implementación interna de cuGraph con múltiples GPU
- Ejecución del WCC
Se ha demostrado el primer paso. Y aunque Ray tiene ganchos NCCL , dependeremos de las interfaces NCCL de RAFT debido a la fuerte dependencia de cuGraph para administrar las comunicaciones. A continuación, se resumen los requisitos que se acaban de describir:
class RAFTActor: def __init__( self , index, pool_size, session_id): ... def broadcast_root_unique_id( self ): # broadcast root/rank-0 to all actors def _setup_nccl( self ): # start NCCL with identified rank-0 actor def _setup_raft( self ): # configure RAFT and NCCL together def set_root_unique_id( self , root_uniqueId): # To be set rank-0 for all actors @ray .remote(num_gpus = 1 ) class WCCActor(RAFTActor): def __init__( self , index, pool_size, session_id): super ().__init__(index = index, pool_size = pool_size, session_id = session_id, actor_name_prefix = "WCC" ) def weakly_connected_components( self , df): """ 1. Each actor loads in a chunk 2. Each actor has a NCCL/RAFT Handle 3. Pass each chunk and handle to MGGraph """ src_array = df[ 'src' ] dst_array = df[ 'dst' ] weights = df[ 'wgt' ] # Configure and setup a Multi-GPU cuGraph Object with # edge list data and NCCL graph = MGGraph(src_array, dst_array, weights, ...) # Execute WCC weakly_connected_components(graph) # Initialize Ray and Run WCC algorithm |
Esto cubre las dos clases necesarias para ejecutar los componentes débilmente conectados de cuGraph. Para obtener más información, consulte una implementación de componentes débilmente conectados . Gran parte del trabajo consiste en configurar NCCL/RAFT. Este mismo patrón funciona para otras bibliotecas como cuML, como se demuestra con la implementación de k-means de cuML .
Conclusión
Ray proporciona una interfaz de actor expresable y escalable que se puede aprovechar fácilmente con RAPIDS. Hemos explorado cómo conectar actores Ray para usar implementaciones optimizadas de CUDA C++ y NCCL. Esta exploración se ha centrado principalmente en la integración de nivel 1 de actores Ray como lanzadores.
Para obtener más información sobre el procesamiento de datos acelerado por GPU, únase a los más de 3500 miembros de la comunidad RAPIDS Slack .
Recursos relacionados
- Curso DLI: Aceleración de los flujos de trabajo de ciencia de datos de extremo a extremo
- Curso DLI: Acelere las operaciones de DataFrame con RAPIDS cuDF
- Sesión de GTC: RAPIDS en 2024: ciencia de datos acelerada en todas partes
- Sesión de GTC: Aceleración del análisis de datos en GPU con el acelerador RAPIDS para Apache Spark
- Kit de desarrollo de software: RÁPIDOS
- Seminario web: Aceleración de Python con GPU
NVIDIA Blog. P. E., A. D. y B. Z. Traducido al español