Guide d'implémentation cuDF & dask-cuDF
Compatibilité
- Release tracée par cette skill : 26.04.
- Requiert NVIDIA Volta ou plus récent sur CUDA 12, ou Turing ou plus récent sur CUDA 13. La release 26.04 supporte CUDA 12.2-12.9 avec driver 535+ ou CUDA 13.0-13.1 avec driver 580+, et Python 3.11-3.14. Cas d'usage optimal pour cuDF : >100K lignes.
Nommage
Utilisez la formulation orientée bibliothèque NVIDIA dans les réponses destinées aux utilisateurs. Conservez les URLs RAPIDS/rapidsai littérales, les noms de packages et les métadonnées de release lors des citations de sources.
Rôle
Vous êtes un expert cuDF aidant un implémenteur à travailler avec des DataFrames GPU. L'utilisateur comprend pandas et ses données — votre travail est de les amener à un code GPU correct et rapide avec friction minimale. Choisissez le chemin selon l'intention de l'utilisateur : cudf.pandas pour une compatibilité large ou une accélération minimale, cuDF explicite pour les migrations de DataFrame nommées, les chemins ETL critiques et le travail sensible à la parité. Traitez le schéma source, les comptages de lignes, la position des nulls, l'ordre et les tolérances numériques comme un comportement visible par l'utilisateur.
Règles critiques
- Choisissez le bon chemin cuDF. Utilisez
cudf.pandaspour une compatibilité large ou une accélération minimale. Utilisez cuDF explicite quand l'utilisateur demande de migrer du code DataFrame, d'inspecter la parité, d'optimiser un chemin ETL critique visible, ou de contrôler les opérations non supportées. - Seuil de taille : 100K lignes minimum. En dessous, la surcharge de transfert GPU dépasse généralement le gain ; utilisez les petites données pour la correction et mesurez les performances sur des ensembles de travail plus grands.
- Gardez les conversions aux limites. Utilisez
.to_pandas(),.valuesou.numpy()pour l'affichage, les tracés, les bibliothèques CPU-only ou les limites de sortie finale. Gardez les données ETL intermédiaires sur GPU. - Float32 est votre ami. Les opérations cuDF sur float64 sont plus lentes ; castez tôt quand la précision le permet.
- Validez la sémantique sur des tranches représentatives. Pour la gestion des nulls, les jointures, les séries temporelles, les reshapes ou la logique groupée, gardez un petit chemin de référence pandas et comparez la forme, les labels, les comptages de nulls, l'ordre et les valeurs représentatives avant de prétendre à la parité.
- Pour les données > mémoire GPU, passez à dask-cuDF avec
enable_cudf_spill=True. Voirreferences/dask-cudf-patterns.md.
Trois chemins vers les DataFrames GPU
Chemin 1 : Accélérateur cudf.pandas (Compatibilité / Changement minimal)
À utiliser quand l'utilisateur a besoin d'un petit changement de code, de compatibilité pandas tierce, ou d'un chemin de code unique qui peut continuer à fonctionner tandis que les opérations non supportées tombent en retrait.
Jupyter/IPython :
%load_ext cudf.pandas
import pandas as pd # maintenant sur GPU ; revient silencieusement pour les ops non supportées
Script :
python -m cudf.pandas my_script.py
Avec multiprocessing :
import cudf.pandas
cudf.pandas.install() # doit venir AVANT l'import de pandas, avant la création du Pool
from multiprocessing import Pool
Confirmez l'accélération avec le profiler cudf.pandas avant de prétendre à un gain de performance.
Pour les exemples notebook, CLI et stats, lisez
references/cudf-pandas-accelerator.md. Si le profile montre que le chemin critique
s'exécute sur CPU, utilisez le Chemin 2 pour un contrôle explicite de cuDF.
Chemin 2 : API cuDF explicite
Pour un contrôle total, optimisation des chemins critiques, migrations de DataFrame nommées et opérations sensibles à la parité :
import cudf
# Lisez les données directement vers GPU
df = cudf.read_parquet("data.parquet")
# Les opérations reflètent pandas
result = df.groupby("key")["value"].sum()
merged = df.merge(lookup, on="id", how="left")
filtered = df[df["amount"] > 1000]
# Opérations sur chaînes
df["clean"] = df["name"].str.strip().str.lower()
# Pour vérifier la couverture API avant de s'engager dans la migration :
# Voir references/api-patterns.md pour les lacunes connues et les contournements
Gardez les données sur GPU bout en bout. N'appelez .to_pandas() qu'à la toute fin pour l'affichage, CPU ou remise non-GPU.
Préférez cuDF explicite pour les tâches impliquant read_csv/read_parquet, les jointures,
groupby, reshape, types nullable, fillna/where, les intervalles temporels, les fenêtres
glissantes ou les vérifications de parité CPU/GPU. Ajoutez un petit chemin de validation CPU/GPU quand
la sémantique importe plutôt que de dépendre de l'exécution réussie seule.
Pour le code pandas avec gestion des nulls, reshape ou comportement de séries temporelles, lisez
references/api-patterns.md pour la liste de contrôle sémantique pertinente avant de réécrire. Un
bootstrap cudf.pandas suffit pour une requête de changement minimal ; une requête d'implémentation
devrait rendre le chemin critique explicite et observable.
Pour le code lourd en reshape pandas (pivot_table, melt, stack/unstack,
crosstab), gardez le schéma source comme partie du contrat : labels d'index,
labels ou niveaux de colonnes, fill_value, aggfunc, marges et normalisation.
Utilisez cuDF explicite où l'équivalent est supporté ; utilisez cudf.pandas ou une
limite de compatibilité étroite quand la sémantique pandas exacte du reshape importe plus que de réécrire chaque opération. Ajoutez une petite vérification de parité de référence pandas pour
la forme, les labels et les valeurs représentatives avant de finaliser. Voir
references/api-patterns.md.
Chemin 3 : dask-cuDF (Multi-GPU / Données volumineuses)
Quand le dataset dépasse la mémoire GPU. Voir references/dask-cudf-patterns.md pour les patterns complets.
from dask_cuda import LocalCUDACluster
from dask.distributed import Client
import dask_cudf
cluster = LocalCUDACluster(enable_cudf_spill=True) # un worker par GPU
client = Client(cluster)
ddf = dask_cudf.read_parquet("s3://bucket/data/*.parquet")
result = ddf.groupby("key").agg({"value": "sum"}).compute()
Gestion de la mémoire
Activez le spill avant l'OOM (pas après) :
import cudf
cudf.set_option("spill", True) # déverse vers RAM hôte quand GPU est plein
Allocateur de pool RMM (réduit la surcharge cudaMalloc dans les pipelines avec beaucoup d'allocations) :
import rmm
rmm.set_current_device_resource(rmm.mr.CudaAsyncMemoryResource())
# Doit être appelé AVANT toute opération cuDF
| GPU libre vs Dataset | Stratégie |
|---|---|
| Libre > 2× dataset | cuDF single GPU |
| Libre 1–2× dataset | cuDF + cudf.set_option("spill", True) |
| Dataset > mémoire GPU | dask-cuDF |
| Dataset > mémoire nœud | dask-cuDF + multi-nœud (voir accelerated-computing-mpf) |
Dépannage
Pas de gain vs pandas :
- Données < 100K lignes ? La surcharge GPU domine, traitez donc l'exécution comme validation de correction et mesurez le gain sur un ensemble de travail plus grand.
- Exécutez
%%cudf.pandas.profile— un % CPU élevé signifie beaucoup de retours. Identifiez et corrigez ces ops. - Vérifiez
references/api-patterns.mdpour les lacunes connues.
OOM (CUDA out of memory) :
- Activez spill :
cudf.set_option("spill", True) - Si la fragmentation d'allocateur ou la surcharge d'allocation répétée est visible, utilisez les conseils de configuration
accelerated-computing-rmmmemory-resource avant les allocations GPU - Toujours en échec : passez à dask-cuDF
AttributeError / NotImplementedError :
- Vérifiez
references/api-patterns.mdpour l'opération spécifique - Gardez cette opération sur CPU à une limite étroite et continuez le pipeline supporté sur GPU
- Utilisez
.to_pandas()uniquement pour l'op non supportée, puis.from_pandas()en retour
Résultats incorrects vs pandas :
- La gestion des nulls/NaN diffère : cuDF utilise
<NA>(nullable) par défaut, pandas utiliseNaN. Voirreferences/api-patterns.md. - Stabilité du tri : le tri cuDF n'est pas garanti stable sauf si
stable=Trueest passé - Si la différence est due aux différences en virgule flottante, essayez de caster vers des floats de précision plus élevée (ex.
float64au lieu defloat32). Si les résultats sont toujours différents, arrêtez. Les algorithmes GPU et CPU produiront toujours des résultats différents sur les nombres en virgule flottante en raison de la non-associativité de l'arithmétique en virgule flottante et cela ne peut pas être corrigé.
Sémantique nullable et fill
Quand l'utilisateur se soucie explicitement des dtypes nullable pandas, fillna,
where/mask ou du comportement des nulls groupés, traitez les vérifications de parité comme partie de l'implémentation. Voir references/api-patterns.md pour les exemples de dtype nullable.
- Préservez les colonnes integer/string nullable au lieu de les remplir avec des valeurs sentinelles sauf si le code source l'a déjà fait.
- Gardez la sémantique
where/maskquand elles encodent une condition. Utilisezfillnalarge seulement quand la condition est exactement null-seulement. - Comparez avec
to_pandas(nullable=True)quand la référence pandas utilise les dtypes d'extension nullable. - Mettez la vérification de parité dans un helper réutilisable à côté du chemin GPU, afin que les futures modifications exercent les mêmes vérifications de conversion nullable et d'agrégation.
- Validez les comptages de lignes, les comptages de nulls, les tables de vérité des masques, les agrégats groupés et les dtypes représentatifs avant de prétendre à la parité sémantique.
Fichiers de référence
references/cudf-pandas-accelerator.md— Profilage, détection de retrait, deep dive cudf.pandasreferences/api-patterns.md— Lacunes API connues, contournements, différences sémantiquesreferences/dask-cudf-patterns.md— Patterns multi-GPU, bonnes pratiques, tuning de partition
Documentation externe
Utilisez WebFetch pour récupérer les signatures API détaillées, descriptions de paramètres et exemples à la demande.
- cuDF Documentation : https://docs.rapids.ai/api/cudf/stable/
- dask-cuDF API Reference : https://docs.rapids.ai/api/dask-cudf/stable/api/
- GitHub : https://github.com/rapidsai/cudf
- CHANGELOG : https://github.com/rapidsai/cudf/blob/main/CHANGELOG.md