
Los conjuntos de puntos grandes contra polígonos grandes solían significar «vuelve mañana». Con CuSpatial, puede ejecutar esas uniones en cuestión de minutos, si su pila está bien configurada. Esta guía muestra una ruta limpia, además del código que puede pegar.
En los alquileres de GPU, su trabajo se ejecuta dentro de una imagen. Dos buenas opciones:
A) Usa una imagen RAPIDS (la más rápida)
<24.xx>docker.io/rapidsai/rapidsai: -cuda12-runtime-ubuntu22.04-py3.10NVIDIA_VISIBLE_DEVICES=TodosNVIDIA_DRIVER_CAPABILITIES=Computación, utilidadB) Use una plantilla CUDA e instale RAPIDS con micromamba
# una vez en una instancia nueva
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
fuente ~/.bashrc
micromamba create -y -n rapids -c rapidsai -c conda-forge rapids=24* python=3,10
micromamba activa rápidos
python -c «importar cudf, cuspatial; print (cudf). __versión__, cuspatial. __versión__)»
Cualquier camino te da brazalete + cuespacial con el espacio de usuario de CUDA listo. El controlador del host normalmente lo suministra el proveedor de servicios informáticos.
Aquí se muestra la API en memoria con un polígono de juguete. Cambie datos reales más adelante.
importar cudf
importar cupy como copla
importar cuspacial
# Puntos (N x 2)
N = 1_000_000
puntos = cudf.DataFrame ({
«x»: cp.random.random (N),
«y»: cp.random.random (N),
})
# Un polígono cuadrado (anillo cerrado)
poly_offsets = cudf.Series ([0], dtype="int32")
ring_offsets = cudf.Series ([0], dtype="int32")
poly_x = cudf.Series ([0, 1, 0, 0], dtype="float64")
poly_y = cudf.Series ([0, 0, 1, 1, 0], dtype="float64")
máscara = cuspatial.point_in_polygon (
puntos ["x"], puntos ["y"],
poly_offsets, ring_offsets,
poly_x, poly_y,
)
# mask es un DataFrame bool (filas=puntos, cols=polígonos)
inside = puntos [mask.iloc [:, 0]]
imprimir (lente (interior))
Notas
máscara tiene una columna por polígono. Usa .cualquiera (eje = 1) si solo te importa si un punto cayó ninguna polígono.Las cargas de trabajo reales utilizan miles de polígonos y cientos de millones de puntos. Evalúe a menos candidatos filtrando primero con casillas delimitadoras y, a continuación, llame punto_in_polígono solo en esos.
importar cudf, ocupar como taza, cupatial
# Supongamos que los puntos y polígonos ya están cargados como cudf
# Ejemplo de estructura poligonal (múltiples polígonos, anillos):
# poly_offsets, ring_offsets, poly_points_x, poly_points_y
# 1) Construye cajas delimitadoras de polígonos (minx, maxx, miny, maxy)
boxes = cuspatial.polygon_bounding_boxes (
poly_offsets, ring_offsets, poly_x, poly_y
)
# cajas: DataFrame [min_x, min_y, max_x, max_y]
#2) Filtro rápido de candidatos: puntos dentro de cualquier casilla
cond = (
(puntos.x >= cajas.min_x.min ()) & (puntos.x <= cajas.max_x.max ()) &
(puntos.y >= boxes.min_y.min ()) & (points.y <= boxes.max_y.max ())
)
pts_cand = puntos [cond]
# 3) Prueba exacta solo para candidatos
máscara = cuspatial.point_in_polygon (
pts_cand.x, pts_cand.y,
poly_offsets, ring_offsets, poly_x, poly_y
)
any_hit = mask.any (eje = 1)
unido = pts_cand [any_hit]
Por qué esto ayuda
El filtrado de cajas delimitadoras reduce la cantidad de costosas pruebas de PIP. Para escalas extremas, consulte las utilidades de árbol cuádruple de CuSpatial para reducir aún más a los candidatos.
importar cudf
points = cudf.read_parquet («sensors_utm.parquet») # columnas: x, y, id
poly = cudf.read_parquet («zones_utm.parquet») # almacenados como anillos explotados
# Construya las matrices de polígonos esperadas por CUSpatial
poly_offsets = poli ["poly_offset"] .astype («int32")
ring_offsets = poli ["ring_offset"] .astype («int32")
poly_x = poli ["x"] .astype («float64")
poly_y = poli ["y"] .astype («float64")
Si los polígonos se encuentran en shapefiles, conviértelos una vez a GeoParquet (sin GPU está bien) para acelerar las cargas futuras.
Para los conjuntos de datos que no caben en una GPU, usa Dask para particionar el trabajo. Patrón:
El código refleja la versión de una sola GPU, pero envuelve los DataFrames de cuDF en Dask cuDF.
Manténgalo aburrido y comparable.
entradas: N_points, N_polygons, vértices de polígonos, CRS, precisión
hardware: modelo de GPU/VRAM, CUDA, controlador
código: versión cuSpatial, ruta exacta del código (con/sin filtro)
métricas: segundos para carga → filtro → PIP, pico de VRAM
Calcular coste por millón de puntos:
cost_por_millón = (precio_por_hora × pared_segundos/ 3600)/(N_puntos/ 1e6)
nvidia-smi. Si está cerca de estar llena, divida la tabla de puntos.Error de CUDA/sin GPU
Comprobar nvidia-smi dentro del contenedor. Asegúrate de que la imagen esté preparada para CUDA y de configurar las variables de entorno de NVIDIA.
MemoryError o OOM
Divida la tabla de puntos; filtre antes con bboxes; reduzca el conjunto de columnas.
Resultados incorrectos
CRS no coincidente. Reproyectar y volver a realizar la prueba. Confirme la orientación del anillo y los polígonos cerrados.
Cargas lentas
Mueva los datos a una NVMe local, cambie a GeoParquet y aumente el tamaño de los grupos de filas de Parquet.
hardware:
gpu: "<model>(<VRAM>GB)»
conductor: "<NVIDIA driver>»
<CUDA version>cuda: "»
software:
<24.xx>imagen: «rapidsai/rapidsai: -cuda12-runtime-ubuntu22.04-py3.10"
pitón: «3.10"
bibliotecas:
<version>- brazalete:»
<version>- cuspacial: «»
entradas:
puntos: "s3://…/sensors_utm.parquet (N=<... >)»
polígonos: "s3://…/zones_utm.parquet (polys=<... >)»
correr:
script: "pip_join.py»
notas: «filtro bbox → PIP; CRS=EPSG:32633"
salidas:
wall_seconds: «<... >»
cost_por_millón: «<... >»
Inicia una instancia de GPU con una plantilla preparada para CUDA (p. ej., Ubuntu 24.04 LTS/CUDA 12.6) o tu propia imagen de GROMACS. Disfrute de una facturación flexible por segundo con plantillas personalizadas y la posibilidad de iniciar, detener y reanudar las sesiones en cualquier momento. ¿No está seguro de los requisitos de FP64? Póngase en contacto con el servicio de asistencia para que le ayuden a seleccionar el perfil de hardware ideal para sus necesidades informáticas.