RAPIDS: Sciences des données accélérées par GPU

Cette page permet de mettre en avant la solution accélérée par GPU RAPIDS(NVIDIA) pour tous travaux de sciences des données et Big Data: analyse de données, visualisation de données, modélisation de données, apprentissage machine (random forest, PCA, arbres gradient boostés, k-means, …). Sur jean Zay, il suffira d'appeler le module pour utiliser RAPIDS, par exemple :

module load rapids/21.08

La solution la plus adaptée pour une étude de données avec RAPIDS sur Jean Zay est d'ouvrir un notebook sur une allocation dynamique sur un nœud de calcul via notre instance JupyterHub.

Sur un nœud de calcul, il n'y a pas de connexion vers internet. Tout installation de librairie ou téléchargement de données devra se faire avant l'allocation dynamique sur un nœud de calcul.

À la fin de cette page vous trouverez un lien vers des notebooks d'exemples de fonctionnalités RAPIDS.

Remarque: cette documentation se limite à l'utilisation de RAPIDS sur un seul nœud. Dans un contexte Big Data, si vous avez la nécessité de distribuer votre étude sur plus de 8 GPU, pour accélérer d'autant plus votre étude ou parce que la taille de la DataFrame manipulée dépasse en mémoire tous les GPU du nœud (au delà de 100 Go), l'assistance IDRIS peut vous aider à configurer un Cluster dimensionné à votre usage sur Jean Zay.

Accélération GPU

L'utilisation de RAPIDS et des GPU devient intéressante par rapport aux solutions classiques sur CPU, lorsque le tableau de données manipulé atteint plusieurs Gigas octets en mémoire. Dans ce cas, l'accélération de la plupart des tâches de lecture/écriture, de prétraitement des données, d'apprentissage machine est notable.

GPURAPIDS

Illustration de l'accélération GPU provenant de la documentation RAPIDS pour un dataset de 400 Go (DGX-2 = 16 GPU V100)

Les API RAPIDS optimisent l'utilisation des GPU pour les travaux d'analyse de données et d'apprentissage machine. Le portage du code python est simple à utiliser : toutes les API RAPIDS reproduisent les fonctionnalités des API de référence dans le traitement par CPU.

EasyRAPIDS

Source: Documentation RAPIDS

Plateforme et API RAPIDS

RAPIDS est bâtit à partir du projet Apache Arrow qui gère le stockage en mémoire de structures de données en colonnes.

Plateforme RAPIDS

Source: Documentation RAPIDS

  • CuDF (correspondance CPU: Pandas ). CuDF est une librairie de DataFrames GPU pour le chargement des données, pour les opérations de fusion, d'agrégation, de filtrage et autres manipulations de données. Exemple:
    import cudf
    tips_df = cudf.read_csv('dataset.csv')
    tips_df['tip_percentage'] = tips_df['tip'] / tips_df['total_bill'] * 100
    # display average tip by dining party size
    print(tips_df.groupby('size').tip_percentage.mean())
  • CuML (correspondance CPU: scikit-learn ). CuML est une librairie d'algorithme de Machine Learning sur données tabulaires compatible avec les autres API RAPIDS et l'API scikit-learn. (XGBOOST peut aussi directement s'utiliser sur les API RAPIDS). Exemple:
    import cudf
    from cuml.cluster import DBSCAN
     
    # Create and populate a GPU DataFrame
    gdf_float = cudf.DataFrame()
    gdf_float['0'] = [1.0, 2.0, 5.0]
    gdf_float['1'] = [4.0, 2.0, 1.0]
    gdf_float['2'] = [4.0, 2.0, 1.0]
     
    # Setup and fit clusters
    dbscan_float = DBSCAN(eps=1.0, min_samples=1)
    dbscan_float.fit(gdf_float)
     
    print(dbscan_float.labels_)
  • CuGraph (correspondance CPU: NetworkX ). CuGraph est une librairie d'analyse de Graph qui prendra en entrée une Dataframe GPU. Exemple:
    import cugraph
     
    # read data into a cuDF DataFrame using read_csv
    gdf = cudf.read_csv("graph_data.csv", names=["src", "dst"], dtype=["int32", "int32"])
     
    # We now have data as edge pairs
    # create a Graph using the source (src) and destination (dst) vertex pairs
    G = cugraph.Graph()
    G.from_cudf_edgelist(gdf, source='src', destination='dst')
     
    # Let's now get the PageRank score of each vertex by calling cugraph.pagerank
    df_page = cugraph.pagerank(G)
     
    # Let's look at the PageRank Score (only do this on small graphs)
    for i in range(len(df_page)):
    	print("vertex " + str(df_page['vertex'].iloc[i]) +
    		" PageRank is " + str(df_page['pagerank'].iloc[i]))
  • Cuxfilter (correspondance CPU: Bokeh / Datashader ). Cuxfilter est une librairie de visualisation de données. Elle permet de connecter un crossfiltering accéléré par GPU à une représentation web.
  • CuSpatial (correspondance CPU: GeoPandas / SciPy.spatial ). Cuspatial est une librairie de traitement de données spatiales incluant les polygônes de point, les jonctions spatiales, les systèmes de coordonnées géographiques, les formes primitives, les distances et les analyses de trajectoire.
  • CuSignal (correspondance CPU: SciPy.signal ). Cusignal est une librairie de traitement du signal.
  • CLX (correspondance CPU: cyberPandas ). CLX est une librairie de traitement et d'analyse de données de cybersécurité.

Accélération Multi-GPU avec Dask-CUDA

La librairie Dask-CUDA permettra d'utiliser les principales API RAPIDS sur plusieurs GPU. Cela permet d'accélérer votre code d'autant plus, et surtout de pouvoir traiter des tableaux de données de plusieurs dizaines ou centaines de Giga octets qui déborderaient la mémoire RAM d'un seul GPU.

Après avoir configurer un cluster, le fonctionnement de Dask se fait comme un workflow. Chaque opération appelée, construit un Graph computationnel. C'est seulement lorsque l'on commande le calcul que celui-ci s'effectue.

from dask.distributed import Client
from dask_cuda import LocalCUDACluster
 
cluster = LocalCUDACluster()
client = Client(cluster)

La calcul du graph se déclenche avec la commande .compute(). Le résultat sera stocké dans la mémoire d'un seul GPU.

import dask_cudf
 
ddf = dask_cudf.read_csv('x.csv')
mean_age = ddf['age'].mean()
mean_age.compute()

Typiquement, dans un workflow dask, où l'on applique plusieurs actions successives sur les données, il sera plus rapide de persister les données dans le cluster (de garder dans la mémoire de chaque GPU les parties des données distribuées et associées à chaque GPU). Pour cela on utilisera la commande .persist().

ddf = dask_cudf.read_csv('x.csv')
ddf = ddf.persist()
ddf['age'].mean().compute()

Exemple avec Cuml:

from dask.distributed import Client
from dask_cuda import LocalCUDACluster
import dask_cudf
import cuml
from cuml.dask.cluster import KMeans
 
cluster = LocalCUDACluster()
client = Client(cluster)
 
ddf = dask_cudf.read_csv('x.csv').persist()
dkm = KMeans(n_clusters=20)
dkm.fit(ddf)
cluster_centers = dkm.cluster_centers_
cluster_centers.columns = ddf.column
labels_predicted = dkm.predict(ddf)
class_idx = cluster_centers.nsmallest(1, 'class1').index[0]
labels_predicted[labels_predicted==class_idx].compute()

Notebooks d'exemple sur Jean Zay

Vous trouverez les notebooks d'exemple (cuml, xgboost, cugraph, cusignal, cuxfilter, clx) présents dans les conteneurs de démonstration de RAPIDS.

Pour copier les notebooks dans votre espace personnel, il faudra exécuter la commande suivante:

 cp -r $DSDIR/examples_IA/Rapids $WORK 

Documentation et sources