
Grandes conjuntos de pontos contra grandes polígonos costumavam significar “volte amanhã”. Com o CuSpatial, você pode executar essas junções em minutos, se sua pilha estiver configurada corretamente. Este guia mostra um caminho limpo, além do código que você pode colar.
Em locatários de GPU, seu trabalho funciona dentro de uma imagem. Duas boas opções:
A) Use uma imagem RAPIDS (mais rápida)
<24.xx>docker.io/rapidsai/rapidsai: -cuda12-runtime-ubuntu22.04-py3.10NVIDIA_VISIBLE_DEVICES=Todosnvidia_driver_capabilities=Computação, utilitárioB) Use um modelo CUDA e instale o RAPIDS com micromamba
# uma vez em uma nova instância
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
fonte ~/.bashrc
micromamba create -y -n rapids -c rapidsai -c conda-forge rapids=24,* python=3,10
micromamba ativa corredeiras
python -c “importar cudf, cuspatial; imprimir (cudf. __version__, cuspatial. __versão__)”
Qualquer caminho te dá manguito + cuspatial com o espaço de usuário CUDA pronto. O driver do host geralmente é fornecido pelo seu provedor de serviços de computação.
Isso mostra a API na memória com um polígono de brinquedo. Troque dados reais posteriormente.
importar cudf
importar cupy como copo
importação causal
# Pontos (N x 2)
N = 1_000_000
pontos = cudf.DataFrame ({
“x”: cp.random.random (N),
“y”: cp.random.random (N),
})
# Um polígono quadrado (anel fechado)
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")
máscara = cuspatial.point_in_polygon (
pontos ["x"], pontos ["y"],
poli_offsets, ring_offsets,
poli_x, poli_y,
)
# mask é um Bool DataFrame (linhas = pontos, colunas = polígonos)
dentro = pontos [mask.iloc [:, 0]]
imprimir (len (dentro))
Notas
mascaram tem uma coluna por polígono. Uso .qualquer (eixo = 1) se você só se importa se um ponto caiu qualquer polígono.Cargas de trabalho reais usam milhares de polígonos e centenas de milhões de pontos. Teste menos candidatos filtrando primeiro com caixas delimitadoras e depois ligue ponto_em_polígono só nesses.
importar cudf, copiar como copo, cuspatial
# Suponha que pontos e polígonos já estejam carregados como cudf
# Exemplo de estrutura poligonal (vários pólipos, anéis):
# poly_offsets, ring_offsets, poly_points_x, poly_points_y
# 1) Construa caixas delimitadoras de polígonos (minx, maxx, miny, maxy)
caixas = cuspatial.polygon_bounding_boxes (
poli_offsets, ring_offsets, poli_x, poli_y
)
# caixas: DataFrame [min_x, min_y, max_x, max_y]
# 2) Filtro rápido de candidatos: pontos em qualquer caixa
segundo = (
(pontos.x >= caixas.min_x.min ()) & (pontos.x <= caixas.max_x.max ()) &
(pontos.y >= caixas.min_y.min ()) e (pontos.y <= boxes.max_y.max ())
)
pts_cand = pontos [cond]
# 3) Teste exato somente em candidatos
máscara = cuspatial.point_in_polygon (
pts_cand.x, pts_cand.y,
poli_offsets, ring_offsets, poli_x, poli_y
)
any_hit = mask.any (eixo = 1)
ingressou = pts_cand [any_hit]
Por que isso ajuda
A filtragem por caixa limite reduz o número de testes PIP caros. Para escalas extremas, veja os utilitários quadtree da CuSpatial para reduzir ainda mais os candidatos.
importar cudf
pontos = cudf.read_parquet (“sensors_utm.parquet”) # cols: x, y, id
poly = cudf.read_parquet (“zones_utm.parquet”) # armazenado como anéis explodidos
# Crie matrizes poligonais esperadas pelo CuSpatial
poly_offsets = poli ["poly_offset"] .astype (“int32")
ring_offsets = poli ["ring_offset"] .astype (“int32")
poli_x = poli ["x"] .astype (“float64")
poli_y = poli ["y"] .astype (“float64")
Se seus polígonos estiverem em shapefiles, converta uma vez em GeoParquet (fora da GPU é bom) para acelerar carregamentos futuros.
Para conjuntos de dados que não cabem em uma GPU, use o Dask para particionar o trabalho. Padrão:
O código espelha a versão de GPU única, mas agrupa DataFrames cuDF no Dask CuDF.
Mantenha-o chato e comparável.
entradas: N_pontos, N_polígonos, vértices poligonais, CRS, precisão
hardware: modelo de GPU/VRAM, CUDA, driver
código: versão CuSpatial, caminho de código exato (com/sem filtro)
métricas: segundos para carregamento → filtro → PIP, pico de VRAM
Computar custo por milhão de pontos:
custo por milhão = (preço_por_hora × segundos_parede/3600)/(N_pontos/1e6)
nvidia-smi. Se estiver quase cheia, fragmente a tabela de pontos.Erro CUDA/sem GPU
Verifique nvidia-smi dentro do contêiner. Certifique-se de que sua imagem esteja pronta para CUDA e defina as variáveis de ambiente da NVIDIA.
Erro de memória ou OOM
Separe a tabela de pontos; filtre cedo com bboxes; reduza o conjunto de colunas.
Resultados errados
CRS incompatível. Reprojete e teste novamente. Confirme a orientação do anel e os polígonos fechados.
Cargas lentas
Mova dados para o NVMe local; mude para o GeoParquet; aumente o tamanho do grupo de linhas do Parquet.
hardware:
gpu: "<model>(<VRAM>GB)”
motorista: "<NVIDIA driver>”
<CUDA version>cuda: "”
software:
<24.xx>imagem: “rapidsai/rapidsai: -cuda12-runtime-ubuntu22.04-py3.10"
python: “3.10"
libs:
<version>- manguito: “”
<version>- cospacial: "”
entradas:
pontos: "s3://…/sensors_utm.parquet (N=<... >)”
polígonos: "s3://…/zones_utm.parquet (polys=<... >)”
executar:
script: "pip_join.py”
notas: “filtro bbox → PIP; CRS=EPSG:32633"
saídas:
wall_seconds: “<... >”
custo por milhão: “<... >”
Inicie uma instância de GPU com um modelo pronto para CUDA (por exemplo, Ubuntu 24.04 LTS/CUDA 12.6) ou sua própria imagem GROMACS. Aproveite o faturamento flexível por segundo com modelos personalizados e a capacidade de iniciar, interromper e retomar suas sessões a qualquer momento. Não tem certeza sobre os requisitos do FP64? Entre em contato com o suporte para ajudá-lo a selecionar o perfil de hardware ideal para suas necessidades computacionais.