El Portal de las Tecnologías para la Innovación

Aceleración del análisis de GPU con RAPIDS y Ray

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)classcuDFActor:    def__init__(self):        ...    defread_parquet(self, filepath: str, columns: list=None) -> cudf.DataFrame:        returncudf.read_parquet(filepath, columns=columns)# Start 4 Workers pool_size =4actor_pool =[cuDFActor.remote() fori inrange(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:

  1. Cargando datos en la memoria de la GPU
  2. Iniciando comunicaciones NCCL (y subcomunicador cuGraph)
  3. Creación de instancias y configuración de la implementación interna de cuGraph con múltiples GPU
  4. 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:

classRAFTActor:    def__init__(self, index, pool_size, session_id):        ...    defbroadcast_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    defset_root_unique_id(self, root_uniqueId):        # To be set rank-0 for all actors@ray.remote(num_gpus=1)classWCCActor(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")    defweakly_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

NVIDIA Blog. P. E., A. D. y B. Z. Traducido al español

Artículos relacionados

Scroll al inicio