El enhebrado OGR / GDAL da como resultado una baja utilización del núcleo

13

Estoy tratando de procesar algunos datos ráster usando ogr / gdal y parece que no puedo obtener la plena utilización de todos los núcleos de mi máquina. Cuando solo ejecuto el proceso en un solo núcleo, obtengo el 100% de utilización de ese núcleo. Cuando trato de dividirme en multinúcleo (en el ejemplo a continuación, al dividir las compensaciones x y ponerlas en una cola), obtengo una utilización patética en cada uno de mis 8 núcleos. Parece que solo agrega hasta un 100% de utilización en cada núcleo (por ejemplo, 12.5% ​​en cada uno).

Me preocupaba que usar el mismo origen de datos fuera el cuello de botella, pero luego dupliqué el archivo ráster subyacente para cada núcleo ... y la utilización del núcleo sigue siendo una mierda. Esto me lleva a creer que ogr o gdal se está comportando de alguna manera como un recurso compartido de cuello de botella, pero no puedo encontrar nada en línea sobre eso. Cualquier ayuda sería muy apreciada!

Esta es la función "auxiliar" que se ejecuta dentro de cada subproceso de trabajo:

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()])
Max
fuente
Poco probable, pero ¿verificaste si la memoria es el cuello de botella?
lynxlynxlynx
@lynxlynxlynx - sí. La memoria definitivamente no es el cuello de botella. He estado tratando de rastrear esto todo el día ... esto es bastante extraño.
Max
Es posible que el controlador ráster que está utilizando simplemente no esté diseñado para ser llamado desde más de un hilo a la vez. Referencia: mail-archive.com/[email protected]/msg07283.html
blah238

Respuestas:

10

OKAY. Ese fue un día de mi vida que nunca volveré otra vez. Resulta que el problema no estaba en el código que publiqué anteriormente. Eso está totalmente bien. Resulta que este fue un caso de subprocesamiento. Subproceso vs. multiprocesamiento. Proceso.

Como se señala en la documentación de Python :

El paquete de multiprocesamiento ofrece concurrencia tanto local como remota, evitando de manera efectiva el bloqueo global del intérprete mediante el uso de subprocesos en lugar de subprocesos. Debido a esto, el módulo de multiprocesamiento permite al programador aprovechar al máximo múltiples procesadores en una máquina determinada

Por lo tanto, threading.Thread es para operaciones intensivas de E / S, multiprocesamiento. El proceso es para operaciones intensivas de CPU. Cambié al multiprocesamiento. Proceso y todo funciona muy bien.

Consulte este tutorial para aprender a usar el multiprocesamiento.

Max
fuente
Solo iba a sugerir que, no estaba seguro de qué implementación (también hay implementaciones de terceros ) que estaba usando :) La he usado recientemente para acelerar una herramienta de sombras de edificios ordenada aquí: Puerto "Produciendo sombras de edificios" Avenida código para ArcGIS 10
blah238
+1 Estaba a punto de publicar que debería tener una palabra en la lista de correo de GDAL-dev; pero ahora estoy contento de que no lo hayas hecho! Esto ha sido guardado para futuras referencias.
MerseyViking
FWIW (probablemente no mucho), leí en algún lugar que la gente está recolectando fondos para tratar de solucionar el problema del bloqueo global del intérprete (GIL). Creo que será por 3.x.
canisrufus