O rosqueamento OGR / GDAL resulta em baixa utilização do núcleo

13

Estou tentando processar alguns dados rasterizados usando ogr / gdal e não consigo obter a utilização completa de todos os núcleos da minha máquina. Quando apenas executo o processo em um único núcleo, obtenho 100% de utilização desse núcleo. Quando tento dividir em multicore (no exemplo abaixo, dividindo os deslocamentos x e colocando-os em uma fila), obtenho uma utilização patética em cada um dos meus 8 núcleos. Parece que apenas adiciona 100% de utilização em cada núcleo (por exemplo, 12,5% em cada).

Eu estava preocupado que o uso da mesma fonte de dados fosse o gargalo, mas dupliquei o arquivo raster subjacente para cada núcleo ... e a utilização do núcleo ainda é uma porcaria. Isso me leva a acreditar que ogr ou gdal está de alguma forma se comportando como um recurso compartilhado por gargalo, mas não consigo encontrar nada online sobre isso. Qualquer ajuda seria muito apreciada!

Esta é a função "auxiliar" que é executada dentro de cada thread do Worker:

def find_pixels_intersect_helper(datasource, bounds_wkt, x_min, x_max):
    bounds = ogr.CreateGeometryFromWkt(bounds_wkt)
    rows_to_write = []
    for x_offset in range(x_min, x_max):
        for y_offset in range(datasource.RasterYSize):
            pxl_bounds_wkt = pix_to_wkt(datasource, x_offset, y_offset)
            pxl_bounds = ogr.CreateGeometryFromWkt(pxl_bounds_wkt)
            if pxl_bounds.Intersect(bounds):
                rows_to_write.append(['%s_%s' % (x_offset, y_offset), pxl_bounds.Centroid().ExportToWkt()])
Máx.
fonte
Improvável, mas você verificou se a memória é o gargalo?
Lynxlynxlynx
@lynxlynxlynx - sim. A memória definitivamente não é o gargalo. Tentando rastrear essa coisa o dia todo ... isso é bem estranho.
Max
Pode ser que o driver de varredura que você está usando simplesmente não tenha sido projetado para ser chamado a partir de mais de um thread por vez. Referência: mail-archive.com/[email protected]/msg07283.html
blah238

Respostas:

10

ESTÁ BEM. Esse foi um dia da minha vida que nunca mais voltarei. Acontece que o problema não estava no código que eu postei acima. Isso é totalmente bom. Acontece que este foi um caso de threading.Thread vs. multiprocessing.Process.

Conforme apontado na documentação do python :

O pacote de multiprocessamento oferece simultaneidade local e remota, efetivamente ultrapassando o bloqueio global de intérpretes usando subprocessos em vez de threads. Devido a isso, o módulo de multiprocessamento permite que o programador aproveite totalmente vários processadores em uma determinada máquina

Assim, threading.Thread é para operações intensivas de IO, multiprocessamento.Process é para operações intensivas de CPU. Eu mudei para multiprocessing.Process e tudo funciona muito bem.

Confira este tutorial para aprender como usar o multiprocessamento.

Máx.
fonte
Eu estava apenas sugerindo que não tinha certeza de qual implementação (também existem implementações de terceiros ) você estava usando :) Eu usei isso recentemente para acelerar uma ferramenta elegante de sombras de construção aqui: Port “Producing Building Shadows” Avenue código para ArcGIS 10
blah238
+1 Eu estava prestes a postar que você deveria ter uma palavra na lista de discussão GDAL-dev; mas agora estou satisfeito por você não! Isso foi esquecido para referência futura.
MerseyViking
FWIW (provavelmente não muito), li em algum lugar que as pessoas estão coletando fundos para tentar corrigir o problema do bloqueio global de intérpretes (GIL). Eu acho que será para 3.x.
Canisrufus 12/06/12