Aller au contenu principal

Calcul de Caractéristiques GPU

Disponible dans : v1.3.0+
Accélération : 5 à 10x plus rapide que le CPU
Corrigé dans v1.6.2 : Les formules GPU correspondent maintenant au CPU (voir les changements incompatibles ci-dessous)

Changement Incompatible dans v1.6.2

Les formules de caractéristiques GPU ont été corrigées pour correspondre au CPU et à la littérature standard (Weinmann et al., 2015). Si vous avez utilisé l'accélération GPU dans v1.6.1 ou antérieure, les valeurs de caractéristiques ont changé. Vous devrez réentraîner les modèles ou passer au CPU pour la compatibilité avec les anciens modèles.

Ce guide couvre les détails techniques du calcul de caractéristiques accéléré par GPU, incluant quelles caractéristiques sont accélérées, la référence API et les techniques d'optimisation avancées.

Caractéristiques Accélérées

Les caractéristiques suivantes sont calculées sur GPU lorsque l'accélération GPU est activée :

Caractéristiques Géométriques de Base

  • Normales de surface (nx, ny, nz) - Vecteurs normaux pour chaque point
  • Valeurs de courbure - Courbure de surface à chaque point
  • Hauteur au-dessus du sol - Valeurs de hauteur normalisées

Caractéristiques Géométriques Avancées

  • Planarité - Mesure du degré de planéité d'une surface (utile pour toits, routes)
  • Linéarité - Mesure des structures linéaires (utile pour bords, câbles)
  • Sphéricité - Mesure des structures sphériques (utile pour végétation)
  • Anisotropie - Mesure de structure directionnelle
  • Rugosité - Texture et irrégularité de surface
  • Densité locale - Densité de points dans le voisinage local

Caractéristiques Spécifiques aux Bâtiments

  • Verticalité - Mesure d'alignement vertical (murs)
  • Horizontalité - Mesure d'alignement horizontal (toits, planchers)
  • Score de mur - Probabilité d'être un élément de mur
  • Score de toit - Probabilité d'être un élément de toit

Performance par Type de Caractéristique

Type de CaractéristiqueTemps CPUTemps GPUAccélération
Normales de Surface2.5s0.3s8.3x
Courbure3.0s0.4s7.5x
Hauteur au-dessus du Sol1.5s0.2s7.5x
Caractéristiques Géom.4.0s0.6s6.7x
Caractéristiques Bât.5.0s0.8s6.3x
Total (1M points)16s2.3s7x

Changements dans v1.6.2

Corrections de Formules

Les formules GPU ont été corrigées pour correspondre au CPU et à la littérature standard :

Avant v1.6.2 (INCORRECT) :

planarity = (λ1 - λ2) / λ0  # Normalisation incorrecte
linearity = (λ0 - λ1) / λ0 # Normalisation incorrecte
sphericity = λ2 / λ0 # Normalisation incorrecte

v1.6.2+ (CORRECT - correspond à Weinmann et al., 2015) :

sum_λ = λ0 + λ1 + λ2
planarity = (λ1 - λ2) / sum_λ # Formulation standard
linearity = (λ0 - λ1) / sum_λ # Formulation standard
sphericity = λ2 / sum_λ # Formulation standard

Nouvelles Fonctionnalités de Robustesse

  1. Filtrage des Cas Dégénérés : Les points avec voisins insuffisants ou valeurs propres proches de zéro retournent maintenant 0.0 au lieu de NaN/Inf
  2. Courbure Robuste : Utilise la Déviation Absolue Médiane (MAD) au lieu de std pour la résistance aux valeurs aberrantes
  3. Support Recherche par Rayon : Recherche de voisinage optionnelle basée sur le rayon (bascule vers CPU)

Validation

Le GPU produit maintenant des résultats identiques au CPU (validé : différence max < 0.0001%) :

# Exécuter le test de validation
python tests/test_feature_fixes.py
# Attendu : ✓✓✓ TOUS LES TESTS RÉUSSIS ✓✓✓

Pour plus de détails, voir :


Référence API

Classe GPUFeatureComputer

La classe principale pour le calcul de caractéristiques accéléré par GPU.

from ign_lidar.features_gpu import GPUFeatureComputer

# Initialiser le calculateur de caractéristiques GPU
computer = GPUFeatureComputer(
use_gpu=True,
batch_size=100000,
memory_limit=0.8,
device_id=0
)

Paramètres du Constructeur

ParamètreTypeDéfautDescription
use_gpuboolTrueActiver l'accélération GPU
batch_sizeint100000Points traités par lot GPU
memory_limitfloat0.8Limite d'utilisation mémoire GPU (0-1)
device_idint0ID du périphérique CUDA (pour multi-GPU)

Méthodes Principales

compute_all_features_with_gpu()

Calculer toutes les caractéristiques pour un nuage de points en utilisant l'accélération GPU.

from ign_lidar.features import compute_all_features_with_gpu
import numpy as np

# Vos données de nuage de points
points = np.random.rand(1000000, 3).astype(np.float32)
classification = np.random.randint(0, 10, 1000000).astype(np.uint8)

# Calculer les caractéristiques
normals, curvature, height, geo_features = compute_all_features_with_gpu(
points=points,
classification=classification,
k=20,
auto_k=False,
use_gpu=True,
batch_size=100000
)

Paramètres :

ParamètreTypeRequisDescription
pointsnp.ndarrayOuiCoordonnées des points (N, 3)
classificationnp.ndarrayOuiClassifications des points (N,)
kintNonNombre de voisins pour les caractéristiques (défaut : 20)
auto_kboolNonAjuster automatiquement k selon la densité (défaut : False)
use_gpuboolNonActiver l'accélération GPU (défaut : True)
batch_sizeintNonTaille de lot pour le traitement GPU (défaut : 100000)

Retourne :

Valeur RetournéeTypeFormeDescription
normalsnp.ndarray(N, 3)Vecteurs normaux de surface
curvaturenp.ndarray(N,)Valeurs de courbure
heightnp.ndarray(N,)Hauteur au-dessus du sol
geo_featuresdict-Dictionnaire de caractéristiques géom

compute_normals_gpu()

Calculer les normales de surface en utilisant le GPU.

from ign_lidar.features_gpu import compute_normals_gpu

normals = compute_normals_gpu(
points=points,
k=20,
batch_size=100000
)

compute_curvature_gpu()

Calculer les valeurs de courbure en utilisant le GPU.

from ign_lidar.features_gpu import compute_curvature_gpu

curvature = compute_curvature_gpu(
points=points,
normals=normals,
k=20,
batch_size=100000
)

compute_geometric_features_gpu()

Calculer toutes les caractéristiques géométriques en utilisant le GPU.

from ign_lidar.features_gpu import compute_geometric_features_gpu

geo_features = compute_geometric_features_gpu(
points=points,
normals=normals,
k=20,
batch_size=100000
)

# Accéder aux caractéristiques individuelles
planarity = geo_features['planarity']
linearity = geo_features['linearity']
sphericity = geo_features['sphericity']

Utilisation Avancée

Optimisation du Traitement par Lots

Pour traiter plusieurs tuiles, réutiliser l'instance de calculateur GPU :

from ign_lidar.features_gpu import GPUFeatureComputer
from pathlib import Path

# Initialiser une fois
computer = GPUFeatureComputer(use_gpu=True, batch_size=100000)

# Traiter plusieurs tuiles
for tile_path in Path("tiles/").glob("*.laz"):
# Charger la tuile
points, classification = load_tile(tile_path)

# Calculer les caractéristiques (GPU reste initialisé)
normals, curvature, height, geo_features = computer.compute_all(
points=points,
classification=classification,
k=20
)

# Sauvegarder les résultats
save_enriched_tile(tile_path, normals, curvature, height, geo_features)

Gestion de la Mémoire

Contrôler l'utilisation de la mémoire GPU pour les grandes tuiles :

from ign_lidar.features_gpu import GPUFeatureComputer

# Pour les très grandes tuiles (>5M points)
computer = GPUFeatureComputer(
use_gpu=True,
batch_size=50000, # Taille de lot plus petite
memory_limit=0.6 # Utiliser moins de mémoire GPU
)

# Pour les tuiles petites à moyennes (moins de 1M points)
computer = GPUFeatureComputer(
use_gpu=True,
batch_size=200000, # Taille de lot plus grande
memory_limit=0.9 # Utiliser plus de mémoire GPU
)

Support Multi-GPU (Expérimental)

Fonctionnalité Expérimentale

Le support multi-GPU est expérimental dans v1.5.0. Utiliser avec précaution en production.

import os

# Spécifier le périphérique GPU
os.environ['CUDA_VISIBLE_DEVICES'] = '0' # Utiliser le premier GPU

# Ou pour un GPU spécifique
computer = GPUFeatureComputer(use_gpu=True, device_id=1) # Utiliser le second GPU

Calcul de Caractéristiques Personnalisées

Implémenter des caractéristiques personnalisées accélérées par GPU :

import cupy as cp
from ign_lidar.features_gpu import GPUFeatureComputer

class CustomGPUComputer(GPUFeatureComputer):
def compute_custom_feature(self, points_gpu):
"""Calculer une caractéristique personnalisée sur GPU"""
# Votre calcul GPU personnalisé utilisant CuPy
feature = cp.mean(points_gpu, axis=1)
return cp.asnumpy(feature)

# Utiliser le calculateur personnalisé
computer = CustomGPUComputer(use_gpu=True)

Conseils d'Optimisation des Performances

1. Taille de Lot Optimale

Choisir la taille de lot selon la mémoire GPU :

Mémoire GPUTaille de Lot RecommandéeNuage de Points Max
4 GB50 0002M points
8 GB100 0005M points
12 GB150 0008M points
16 GB+200 000+10M+ points

2. Sélection de K-Neighbors

Les valeurs k plus grandes bénéficient plus du GPU :

# Optimal pour GPU (k >= 20)
features = compute_all_features_with_gpu(points, classification, k=20, use_gpu=True)

# Moins optimal pour GPU (k < 10)
features = compute_all_features_with_gpu(points, classification, k=5, use_gpu=True)

3. Optimisation des Transferts Mémoire

Minimiser les transferts CPU-GPU en regroupant les opérations :

# ❌ Mauvais : Transferts multiples
normals = compute_normals_gpu(points)
curvature = compute_curvature_gpu(points, normals) # Transférer normales retour
geo = compute_geometric_features_gpu(points, normals) # Transférer à nouveau

# ✅ Bon : Lot unique
normals, curvature, height, geo = compute_all_features_with_gpu(points, classification)

4. Mémoire GPU Persistante

Pour le traitement répété, garder les données sur GPU :

import cupy as cp

# Transférer vers GPU une fois
points_gpu = cp.asarray(points)

# Traiter plusieurs fois sans re-transfert
for k in [10, 20, 30]:
normals = compute_normals_gpu(points_gpu, k=k)

Benchmark

Exécuter les Benchmarks

La bibliothèque inclut des outils de benchmark complets :

# Benchmark synthétique (test rapide)
python scripts/benchmarks/benchmark_gpu.py --synthetic

# Benchmark avec données réelles
python scripts/benchmarks/benchmark_gpu.py path/to/tile.laz

# Benchmark multi-tailles
python scripts/benchmarks/benchmark_gpu.py --multi-size

# Comparer différentes valeurs de k
python scripts/benchmarks/benchmark_gpu.py --test-k

Interprétation des Résultats

Exemple de sortie de benchmark :

GPU Benchmark Results
=====================
GPU Model: NVIDIA RTX 3080 (10GB)
CUDA Version: 11.8
CuPy Version: 11.6.0

Point Cloud: 1,000,000 points
K-neighbors: 20

Feature Computation Times:
--------------------------
Normals (CPU): 2.45s
Normals (GPU): 0.31s → 7.9x speedup

Curvature (CPU): 2.98s
Curvature (GPU): 0.42s → 7.1x speedup

Geometric (CPU): 3.87s
Geometric (GPU): 0.58s → 6.7x speedup

Total (CPU): 15.32s
Total (GPU): 2.14s → 7.2x speedup

Memory Usage:
-------------
GPU Memory Used: 1.2 GB / 10 GB (12%)
Peak Memory: 1.8 GB
CPU Memory Used: 2.4 GB

Facteurs de Performance

Les performances GPU dépendent de :

  1. Taille du nuage de points : Plus grand = meilleure utilisation GPU
  2. Valeur K-neighbors : Plus grand = plus de travail parallélisable
  3. Modèle GPU : Plus récent = traitement plus rapide
  4. Bande passante mémoire : Plus élevée = transferts plus rapides
  5. Capacité de calcul CUDA : Plus élevée = plus de fonctionnalités

Dépannage

Problèmes de Performance

GPU Plus Lent que Prévu

Symptômes : Le traitement GPU n'est pas beaucoup plus rapide que le CPU

Causes Possibles :

  1. Petits nuages de points (<10K points) - La surcharge GPU domine
  2. Valeur k faible (<10) - Pas assez de travail parallélisable
  3. Goulot d'étranglement de transfert mémoire
  4. GPU pas entièrement utilisé

Solutions :

# Vérifier l'utilisation GPU
nvidia-smi -l 1

# Devrait afficher une utilisation GPU élevée pendant le traitement
# Si l'utilisation GPU est faible :
# Augmenter la taille de lot
computer = GPUFeatureComputer(batch_size=200000)

# Augmenter la valeur k
features = compute_all_features_with_gpu(points, classification, k=30)

# Utiliser des tuiles plus grandes ou du traitement par lots

Erreurs de Mémoire Insuffisante

Symptômes : Erreurs CUDA de mémoire insuffisante

Solutions :

# Réduire la taille de lot
computer = GPUFeatureComputer(batch_size=50000)

# Réduire la limite mémoire
computer = GPUFeatureComputer(memory_limit=0.6)

# Traiter par morceaux plus petits
for chunk in split_point_cloud(points, chunk_size=500000):
features = compute_all_features_with_gpu(chunk, classification)

Erreurs d'Importation CuPy

Symptômes : ImportError ou avertissements d'incompatibilité de version CUDA

Solutions :

# Vérifier la version CUDA
nvidia-smi | grep "CUDA Version"

# Réinstaller CuPy correspondant
pip uninstall cupy
pip install cupy-cuda11x # ou cupy-cuda12x

Fuites Mémoire

Si la mémoire GPU continue d'augmenter :

# Forcer le nettoyage de la mémoire GPU
import cupy as cp
cp.get_default_memory_pool().free_all_blocks()

# Ou utiliser un gestionnaire de contexte
from ign_lidar.features_gpu import GPUMemoryManager

with GPUMemoryManager():
# Mémoire GPU automatiquement libérée après ce bloc
features = compute_all_features_with_gpu(points, classification)

Limitations

Limitations Actuelles

  1. Mémoire GPU : Limitée par la RAM GPU disponible
  2. GPU Unique : Le support multi-GPU est expérimental
  3. NVIDIA Uniquement : Nécessite un GPU NVIDIA avec CUDA
  4. Implémentation K-NN : Utilise force brute pour k < 50, KD-tree pour k >= 50

Améliorations Futures (Feuille de Route)

  • 🔄 Support Multi-GPU (v1.6.0) - Distribuer le travail sur plusieurs GPUs
  • 🔄 Précision Mixte (v1.6.0) - Utiliser FP16 pour un calcul plus rapide
  • 🔄 Support GPU AMD (v2.0.0) - Support ROCm pour GPUs AMD
  • 🔄 Traitement par Morceaux (v1.6.0) - Découpage automatique pour très grandes tuiles
  • 🔄 Cache GPU Persistant (v1.7.0) - Mettre en cache les données prétraitées sur GPU

Voir Aussi

Références