← Blog
September 1, 2025

Leia e processe GeoTiffs na GPU (CuCim + rasterio)

Você pode executar cálculos rasterizados pesados em uma única GPU se carregar dados em azulejos e mantenha o georreferenciamento em linha reta. Este guia mostra um padrão claro para usar com seu provedor de serviços de GPU usando rastério para metadados e E/S, Cucum/cupy para velocidade e pyproj quando você precisa de reprojeção.

Pura verdade: nem todo GeoTIFF lê nativamente na GPU. O caminho confiável é Leitura da CPU → Computação da GPU → Gravação da CPU, feito em janelas que correspondem ao mosaico interno do arquivo. O CuCim pode ler muitos TIFFs ladrilhados diretamente na GPU; quando não consegue, você ainda ganha copiando janelas para o CuPy antes da matemática.

1) Escolha uma imagem

Duas boas opções:

A) Imagem RAPIDS (início rápido)
<24.xx>docker.io/rapidsai/rapidsai: -cuda12-runtime-ubuntu22.04-py3.10

B) Base CUDA+bibliotecas Python
Comece com um tempo de execução CUDA (por exemplo, Ubuntu 24.04/CUDA 12.x) e instale:

# micromamba (recomendado)
micromamba cria -y -n geo -c conda-forge -c rapidsai\
python=3.10 rasterio pyproj cudf cupy cucim
micromamba ative geo
python -c “importar rasterio, pyproj, cupy, cucim; print ('ok')”

Seu modelo deve definir:

  • NVIDIA_VISIBLE_DEVICES=Todos
  • nvidia_driver_capabilities=Computação, utilitário

Verificação de sanidade dentro do contêiner:

nvidia-smi

2) Use GeoTiffs otimizados para nuvem (COGs) quando puder

Loja COGs ladrilhos internos e visões gerais que tornam a leitura em janelas previsível. Mesmo para arquivos locais, o layout COG mantém a E/S rápida e funciona bem com o mosaico da GPU. Se você puder, converta uma vez em um COG com 512 × 512 ou 1024 × 1024 peças e LZW/Deflate/ZSTD.

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

3) Padrão A — Leitura da CPU → Computação da GPU → Gravação da CPU (padrão robusto)

Isso funciona em qualquer GeoTIFF e mantém o georreferenciamento intacto.

Exemplo: NDVI das bandas RED/NIR

importar rasterio
da janela de importação rasterio.windows
importar cupy como copo
importar numpy como np

src_path = "scene.tif" # GeoTIFF multibanda (por exemplo, banda 3=RED, banda 4=NIR)
dst_path = "ndvi.tif”
BANDA_VERMELHA, BANDA_PRETA = 3, 4

com rasterio.open (src_path) como src:
perfil = src.profile.copy ()
profile.update (count=1, dtype="float32", nodata=np.nan)

tile_w, tile_h = src.block_shapes [0] # usa ladrilhos internos
com rasterio.open (dst_path, “w”, **profile) como dst:
para ji, janela em src.block_windows (1): # iterate tiles
vermelho = src.read (RED_BAND, janela = janela) .astype (“float32")
nir = src.read (NIR_BAND, janela = janela) .astype (“float32")

# mudar para a GPU
red_d = cp.asarray (vermelho)
nir_d = cp.asarray (nir)

# NDVI = (NIR - VERMELHO)/(NIR + VERMELHO)
denom = nir_d + red_d
ndvi_d = cp.where (denom! = 0, (nir_d - red_d) /denom, cp.nan)

# voltar para a CPU e escrever
dst.write (cp.asnumpy (ndvi_d), 1, janela=janela)

Por que isso funciona

  • Alças Rasterio CRS/Transform/Sem dados e grava um GeoTIFF válido.
  • Você só move um azulejo por vez na GPU, para que a VRAM permaneça limitada.
  • Funciona com entradas comprimidas; a descompressão ocorre durante src.read ().

4) Padrão B — leitura nativa da GPU com CUCim (quando suportado)

O CUCim pode ler muitos TIFFs em mosaico diretamente na GPU sem uma matriz de CPU intermediária. Você ainda usa o rasterio para buscar metadados e gravar saídas.

importar rasterio
importar cupy como copo
de cucim import CuImage
da janela de importação rasterio.windows

src_path = "scene.tif”
banda_vermelha, banda_preta = 3, 4

com rasterio.open (src_path) como src:
H, W = src.height, src.width
tile_w, tile_h = src.block_shapes [0]

cu = CuImage (src_path)

profile = src.profile.copy (); profile.update (count=1, dtype="float32")
com rasterio.open (” ndvi.tif “, “w”, **profile) como dst:
para _, janela em src.block_windows (1):
col_off, row_off = window.col_off, window.row_off
w, h = janela.largura, janela.altura

# Leia uma sub-região (x, y, w, h) diretamente na GPU
# Nota: alguns arquivos/drivers podem exigir substitutos; manipule exceções.
região = cu.read_region (
localização = (col_off, row_off), tamanho = (w, h), nível = 0
) # retorna uma matriz com bands-last
# corte as bandas e vá para o CuPy
nir_d = cp.asarray (região [..., nir_band - 1], dtype=cp.float32)
red_d = cp.asarray (região [..., red_band - 1], dtype=cp.float32)

ndvi_d = (nir_d - vermelho_d)/cp.where ((nir_d + vermelho_d)! = 0, (nir_d + vermelho_d), cp.nan)
dst.write (cp.asnumpy (ndvi_d), 1, janela=janela)

Advertências

  • A ordem da banda pode ser bands‑last; ajustar a indexação.
  • Alguns recursos do GeoTIFF não são totalmente suportados pelo CUCim; detecte exceções e volte para o Padrão A.

5) Reprojeção (mantenha a simplicidade)

Faça a matemática de distorção uma vez na CPU para produzir um grade de destinoe, em seguida, faça uma amostra na GPU.

importar numpy como np, cupy como cp, rasterio
de rasterio.warp importe calculate_default_transform
de rasterio.vrt importe WarpeDVRT

src = rasterio.open (” scene.tif “)
dst_crs = “EPSG:32633" # exemplo de UTM
transformação, largura, altura = calculate_default_transform (src.crs, dst_crs, src.width, src.height, *src.bounds)

# Crie uma visão virtual distorcida (o rasterio lida com geodésia e reamostragem)
com warpedVrt (src, crs=dst_crs, transform=transform, width=width, height=height, resampling=rasterio.enums.resampling.bilinear) como vrt:
perfil = vrt.profile.copy (); profile.update (dtype="float32", count=1)
com rasterio.open (” band3_utm.tif “, “w”, **profile) como dst:
para _, janela em vrt.block_windows (1):
arr = vrt.read (3, janela = janela) .astype (“float32")
# faça cálculos de GPU nos blocos distorcidos, se necessário
arr_d = cp.asarray (arr)
#... computar...
dst.write (cp.asnumpy (arr_d), 1, janela = janela)

Por que essa abordagem

  • Você mantém geodésia (transformações CRS, reamostragem de kernels) em uma biblioteca testada em batalha.
  • Você ainda obtém acelerações de GPU para pessoas pesadas matemática por pixel depois de dobra.

6) Dicas de desempenho e VRAM

  • Combine o tamanho do bloco do arquivo (conjunto de dados.block_shapes) para janelas; não invente tamanhos ímpares.
  • Prefiro float32 para cálculos, a menos que você tenha provado que o FP64 é necessário.
  • Limitar blocos simultâneos; processe de 1 a 4 por vez, dependendo da VRAM.
  • Evite a sobrecarga por bloco do Python agrupando janelas e usando loops simples.
  • Grave arquivos menores e maiores (ou COGs com revestimento interno) para reduzir a sobrecarga de metadados.

7) Autoavaliação e matemática de custos

entradas: tamanho do arquivo, bandas, dtype, blocos, CRS
hardware: modelo de GPU/VRAM, CUDA, driver; modelo de CPU
código: versões (rasterio, cucim, cupy)
métricas: ladrilhos/seg, MB/seg, tempo de parede, pico de VRAM

Custo por 100 GB processados

custo_por_100gb = preço_por_hora × horas_parede × (100/ (gb_processado))

8) Solução de problemas

SALA DE GPU
Processe menos ou maiores blocos; converta em float32; matrizes livres (del arr_d; cp._default_memory_pool.free_all_blocks ()).

Resultados estranhos
Bandas incompatíveis ou sem tratamento de dados. Verifique a ordem das bandas; propague nenhum dado para a saída.

Leituras lentas
Não é um COG, ladrilhos minúsculos ou compressão pesada. Converta uma vez em um COG bem revestido.

Erros CUCim
Volte para o Padrão A e registre as informações de criação do arquivo para posterior conversão.

Trecho de métodos (copiar e colar)

hardware:
gpu: "<model>(<VRAM>GB)”
motorista: "<NVIDIA driver>”
<CUDA version>cuda: "”
software:
<24.xx>imagem: “rapidsai/rapidsai: -cuda12-runtime-ubuntu22.04-py3.10"
libs:
<ver>- rasterio: "”
<ver>- cominho: "”
<ver>- xícara: “”
<ver>- pyproj: "”
entradas:
arquivo: "scene.tif (bands=<... >, dtype=<... >)”
<EPSG:...>grade: “CRS=, transform=< ... >”
executar:
padrão: “Leitura da CPU → computação da GPU → gravação da CPU (blocos)”
bloco: "<w>× <h>de block_shapes”
saídas:
wall_seconds: “<... >”
telhas_por_seg: “<... >”
mb_per_sec: “<... >”
notas: “COG? compressão? reamostragem? sem propagação de dados”

Leitura relacionada

Experimente o Compute hoje

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.