← Back

GPU géospatial avec RAPIDS CUspatial : jointures spatiales et point dans un polygone

Les grands ensembles de points contre de grands polygones signifiaient autrefois « revenez demain ». Avec CuSpatial, vous pouvez exécuter ces jointures en quelques minutes, si votre stack est correctement configuré. Ce guide montre un chemin propre, ainsi que du code que vous pouvez coller.

Ce que nous allons couvrir

  • Choisir un Modèle prêt pour CUDA (ou une image RAPIDS)
  • Obtenir CUDF/CUSpatial prêt sans rasage
  • Deux modèles principaux : point dans un polygone et point dans un polygone à l'échelle (avec filtrage spatial)
  • Un petit auto‑évaluation harnais
  • Pièges liés à la VRAM, aux E/S et à la projection

Start in seconds with the fastest, most affordable cloud GPU clusters.

Launch an instance in under a minute. Enjoy flexible pricing, powerful hardware, and 24/7 support. Scale as you grow—no long-term commitment needed.

Try Compute now

1) Choisissez votre image

Sur les locataires du GPU, votre tâche s'exécute à l'intérieur d'une image. Deux bonnes options :

A) Utilisez une image RAPIDS (la plus rapide)

  • Registre (image) : <24.xx>docker.io/rapidsai/rapidsai : -cuda12-runtime-ubuntu22.04-py3.10
  • L'environnement varie :
    • NVIDIA Visible_Devices = Tous
    • NVIDIA Driver_Capabilities=Calcul, utilitaire
  • CMD : conservez votre script de démarrage ou un shell interactif.

B) Utilisez un modèle CUDA et installez RAPIDS avec micromamba

# une seule fois dans une nouvelle instance
curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba
mkdir -p ~/micromamba &&. /bin/micromamba shell init -s bash -p ~/micromamba
source ~/.bashrc
micromamba create -y -n rapids -c rapidsai -c conda-forge rapids=24.* python=3,10
micromamba active les rapides
python -c « import cudf, cuspatial ; print (cudf) ». __version__, cuspatial. __version__) »

L'un ou l'autre chemin vous donne brassard + cuspatial avec l'espace utilisateur CUDA prêt. Le pilote hôte est généralement fourni par votre fournisseur de services informatiques.

2) Des formats de données qui fonctionnent bien

  • Géoparquet pour les points et les polygones. Il est colonnaire et convivial pour CuDF.
  • Shapefile fonctionne, mais préférez passer une fois à GeoParquet.
  • VOITURES: reprojeter vers une métrique CRS (par exemple, UTM) avant le calcul de la distance ou de la surface. Conservez tout dans même CRS.

3) Point‑dans‑Polygon (PIP) : le schéma de base

Cela montre l'API en mémoire avec un polygone jouet. Échangez les données réelles plus tard.

brassard d'importation
importation de cupy en tant que tasse
importation cuspatial

Nombre de points (N x 2)
N = 1 000_000
points = CUDF.DataFrame ({
« x » : cp.random.random (N),
« y » : cp.random.random (N),
})

# Un polygone carré (anneau fermé)
poly_offsets = CUDF.series ([0], dtype="int32")
ring_offsets = CUDF.series ([0], dtype="int32")
poly_x = CUDF.series ([0, 1, 1, 0, 0], dtype="float64")
poly_y = CUDF.series ([0, 0, 1, 1, 0], dtype="float64")

masque = cuspatial.point_in_polygon (
points ["x"], points ["y"],
poly_offsets, ring_offsets,
poly_x, poly_y,
)
# mask est un DataFrame bool (rows=points, cols=polygones)
intérieur = points [mask.iloc [:, 0]]
impression (lentille (intérieur))

Remarques

  • Pour plusieurs polygones, masque comporte une colonne par polygone. Utiliser .any (axis=1) si vous vous souciez seulement de savoir si un point est perdu n'importe quel polygone.
  • Utiliser float64 pour les coordonnées des polygones si votre domaine en a besoin ; les points peuvent être au format float32/64.

4) PIP à grande échelle : filtrez puis testez

Les charges de travail réelles utilisent des milliers de polygones et des centaines de millions de points. Testez moins de candidats en filtrant d'abord à l'aide de cadres de sélection, puis appelez point_dans_polygone juste sur ceux-là.

manchette d'importation, tasse en forme de tasse, couspatial

# Supposons que les points et les polygones sont déjà chargés en tant que cudf
# Exemple de structure polygonale (polys multiples, anneaux) :
# poly_offsets, poly_points_x, poly_points_y

# 1) Créez des cadres de délimitation de polygones (minx, maxx, miny, maxy)
boîtes = cuspatial.polygon_bounding_boxes (
poly_offsets, poly_offsets, poly_x, poly_y
)
# cases : DataFrame [min_x, min_y, max_x, max_y]

# 2) Filtre rapide des candidats : points dans n'importe quelle case
deuxième = (
(points.x >= boxes.min_x.min ()) & (points.x <= boxes.max_x.max ()) et
(points.y >= boxes.min_y.min ()) & (points.y <= boxes.max_y.max ())
)
pts_cand = points [seconde]

# 3) Test exact uniquement sur les candidats
masque = cuspatial.point_in_polygon (
pts_cand.x, pts_cand.y,
poly_offsets, poly_offsets, poly_x, poly_y
)
any_hit = masque.any (axis=1)
joint = pts_cand [any_hit]

Pourquoi cela aide
Le filtrage Bounding‑box réduit le nombre de tests PIP coûteux. Pour les échelles extrêmes, consultez les utilitaires quadtree de CuSpatial pour élaguer encore plus les candidats.

5) Lecture de données réelles (GeoParquet)

brassard d'importation

points = cudf.read_parquet (« sensors_utm.parquet ») # colonnes : x, y, id
poly = cudf.read_parquet (« zones_utm.parquet ») # stocké sous forme d'anneaux éclatés

# Construire des tableaux de polygones attendus par CuSpatial
poly_offsets = poly ["poly_offset"] .astype (« int32")
ring_offsets = poly ["ring_offset"] .astype (« int32")
poly_x = poly ["x"] .astype (« float64")
poly_y = poly ["y"] .astype (« float64")

Si vos polygones se trouvent dans des fichiers de formes, convertissez-les une fois en GeoParquet (hors GPU, c'est bien) pour accélérer les futurs chargements.

6) Demandez des tâches dont la taille dépasse celle du processeur graphique (facultatif)

Pour les ensembles de données qui ne rentrent pas dans un seul GPU, utilisez Dask pour partitionner le travail. Motif :

  • Partitionnez les points entre les travailleurs/les GPU.
  • Diffusez des polygones (généralement plus petits) aux travailleurs.
  • Filtrez les candidats par partition, puis PIP.

Le code reflète la version à GPU unique mais enveloppe les DataFrames cuDF dans Dask CuDF.

7) Harnais à auto-évaluation

Faites en sorte que ce soit ennuyeux et comparable.

entrées : N_points, N_polygones, sommets de polygones, CRS, précision
matériel : modèle GPU/VRAM, CUDA, pilote
code : version CUSpatial, chemin de code exact (avec/sans filtre)
métriques : secondes pour charger → filtre → PIP, pic de VRAM

Calculer coût par million de points:

coût_per_million = (prix_par_heure × wall_secondes/3600)/(N_points/1e6)

8) Conseils sur la VRAM et les performances

  • VRAM: gardez un œil sur nvidia-smi. S'il est presque plein, découpez le tableau des points.
  • VOITURES: reprojetez une fois vers un CRS métrique avant les opérations de distance/zone ; stockez-le dans GeoParquet.
  • E/S: lisez Parquet depuis le NVMe local. Pour les compartiments cloud, utilisez des groupes de lignes plus grands et snappy/zstd.
  • Précision: float32 est plus rapide et plus petit. Utilisez float64 uniquement si la validation l'exige.
  • Journalisation: chronométrez chaque étape (chargement, filtre, PIP) séparément ; cela vous permet de voir les goulots d'étranglement.

9) Résolution des problèmes

Erreur CUDA/pas de GPU
Vérifiez nvidia-smi à l'intérieur du conteneur. Assurez-vous que votre image est prête pour CUDA et que vous définissez les variables d'environnement NVIDIA.

MemoryError ou OOM
Divisez le tableau de points ; filtrez tôt avec des bboxes ; réduisez le jeu de colonnes.

Des résultats erronés
CRS non apparié. Reprojetez et testez à nouveau. Confirmez l'orientation de l'anneau et les polygones fermés.

Charges lentes
Déplacez les données vers le NVMe local ; passez à GeoParquet ; augmentez la taille du groupe de lignes Parquet.

Extrait de méthodes (copier-coller)

matériel :
processeur graphique : « <model>(<VRAM>Go) »
chauffeur : « <NVIDIA driver>»
<CUDA version>cuda : « »
logiciel :
<24.xx>image : « rapidsai/rapidsai : -cuda12-runtime-ubuntu22.04-py3.10"
python : « 3,10 »
bibliothèques :
<version>- manchette : « »
<version>- spatial : « »
entrées :
points : « s3://…/sensors_utm.parquet (N=<... >) »
polygones : « s3://…/zones_utm.parquet (polys=<... >) »
courir :
script : « pip_join.py »
remarques : « filtre bbox → PIP ; CRS=EPSG:32633"
sorties :
wall_seconds : « <... > »
coût_par_million : « <... > »

Lecture associée

Essayez Compute dès aujourd'hui

Démarrez une instance GPU avec un modèle compatible CUDA (par exemple, Ubuntu 24.04 LTS/CUDA 12.6) ou votre propre image GROMACS. Profitez d'une facturation flexible à la seconde avec modèles personnalisés et la possibilité de démarrer, d'arrêter et de reprendre vos sessions à tout moment. Vous n'êtes pas sûr des exigences du FP64 ? Contactez le support pour vous aider à sélectionner le profil matériel le mieux adapté à vos besoins informatiques.

← Back