Un requisito común en los SIG es aplicar una herramienta de procesamiento a varios archivos o aplicar un proceso para una serie de características de un archivo a otro.
Muchas de estas operaciones son vergonzosamente paralelas en el sentido de que los resultados de los cálculos de ninguna manera influyen en ninguna otra operación en el ciclo. No solo eso, sino que a menudo los archivos de entrada son distintos.
Un ejemplo clásico es la disposición en mosaico de archivos de formas contra archivos que contienen polígonos para recortarlos.
Aquí hay un método de procedimiento clásico (probado) para lograr esto en un script de Python para QGIS. (Para su información, la salida de archivos de memoria temporal a archivos reales más de la mitad del tiempo para procesar mis archivos de prueba)
import processing
import os
input_file="/path/to/input_file.shp"
clip_polygons_file="/path/to/polygon_file.shp"
output_folder="/tmp/test/"
input_layer = QgsVectorLayer(input_file, "input file", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(input_layer)
tile_layer = QgsVectorLayer(clip_polygons_file, "clip_polys", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(tile_layer)
tile_layer_dp=input_layer.dataProvider()
EPSG_code=int(tile_layer_dp.crs().authid().split(":")[1])
tile_no=0
clipping_polygons = tile_layer.getFeatures()
for clipping_polygon in clipping_polygons:
print "Tile no: "+str(tile_no)
tile_no+=1
geom = clipping_polygon.geometry()
clip_layer=QgsVectorLayer("Polygon?crs=epsg:"+str(EPSG_code)+\
"&field=id:integer&index=yes","clip_polygon", "memory")
clip_layer_dp = clip_layer.dataProvider()
clip_layer.startEditing()
clip_layer_feature = QgsFeature()
clip_layer_feature.setGeometry(geom)
(res, outFeats) = clip_layer_dp.addFeatures([clip_layer_feature])
clip_layer.commitChanges()
clip_file = os.path.join(output_folder,"tile_"+str(tile_no)+".shp")
write_error = QgsVectorFileWriter.writeAsVectorFormat(clip_layer, \
clip_file, "system", \
QgsCoordinateReferenceSystem(EPSG_code), "ESRI Shapefile")
QgsMapLayerRegistry.instance().addMapLayer(clip_layer)
output_file = os.path.join(output_folder,str(tile_no)+".shp")
processing.runalg("qgis:clip", input_file, clip_file, output_file)
QgsMapLayerRegistry.instance().removeMapLayer(clip_layer.id())
Esto estaría bien, excepto que mi archivo de entrada es de 2GB y el archivo de recorte de polígonos contiene más de 400 polígonos. El proceso resultante lleva más de una semana en mi máquina de cuatro núcleos. Mientras tanto, tres núcleos están inactivos.
La solución que tengo en mi cabeza es exportar el proceso a archivos de script y ejecutarlos de forma asíncrona usando gnu paralelo, por ejemplo. Sin embargo, parece una pena tener que abandonar QGIS en una solución específica del sistema operativo en lugar de usar algo nativo de QGIS python. Entonces mi pregunta es:
¿Puedo paralelizar operaciones geográficas embarazosamente paralelas de forma nativa dentro de Python QGIS?
Si no es así, ¿tal vez alguien ya tenga el código para enviar este tipo de trabajo a scripts de shell asíncronos?
fuente
Respuestas:
Si cambia su programa para leer el nombre del archivo desde la línea de comandos y divide su archivo de entrada en fragmentos más pequeños, puede hacer algo como esto usando GNU Parallel:
Esto ejecutará 1 trabajo por núcleo.
Todas las computadoras nuevas tienen múltiples núcleos, pero la mayoría de los programas son de naturaleza serial y, por lo tanto, no utilizarán los múltiples núcleos. Sin embargo, muchas tareas son extremadamente paralelizables:
GNU Parallel es un paralelizador general y hace que sea fácil ejecutar trabajos en paralelo en la misma máquina o en varias máquinas a las que tiene acceso ssh.
Si tiene 32 trabajos diferentes que desea ejecutar en 4 CPU, una forma directa de paralelizar es ejecutar 8 trabajos en cada CPU:
GNU Parallel genera un nuevo proceso cuando uno termina, manteniendo las CPU activas y ahorrando así tiempo:
Instalación
Si GNU Parallel no está empaquetado para su distribución, puede hacer una instalación personal, que no requiere acceso de root. Se puede hacer en 10 segundos haciendo esto:
Para otras opciones de instalación, consulte http://git.savannah.gnu.org/cgit/parallel.git/tree/README
Aprende más
Ver más ejemplos: http://www.gnu.org/software/parallel/man.html
Mira los videos de introducción: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Recorre el tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html
Regístrese en la lista de correo electrónico para obtener asistencia: https://lists.gnu.org/mailman/listinfo/parallel
fuente
my_processing.py
Puede encontrar una buena formulación para usted en gis.stackexchange.com/a/130337/26897En lugar de utilizar el método paralelo GNU, puede utilizar el módulo de multiprocesamiento de Python para crear un grupo de tareas y ejecutarlas. No tengo acceso a una configuración de QGIS para probarlo, pero se agregó multiproceso en Python 2.6, por lo que siempre que esté usando 2.6 o posterior, debería estar disponible. Hay muchos ejemplos en línea sobre el uso de este módulo.
fuente
Aquí está la solución paralela GNU. Con un poco de cuidado, la mayoría de los algoritmos ogr o saga basados en linux de forma paralela podrían ejecutarse dentro de su instalación QGIS.
Obviamente esta solución requiere la instalación de GNU en paralelo. Para instalar gnu paralelo en Ubuntu, por ejemplo, vaya a su terminal y escriba
Nota: no pude hacer que el comando de shell paralelo funcionara en Popen o en un subproceso, lo que hubiera preferido, así que pirateé una exportación a un script bash y ejecuté eso con Popen.
Aquí está el comando de shell específico usando paralelo que envolví en python
Cada {1} se intercambia por un número del rango {1..400} y luego los cuatrocientos comandos de shell se gestionan mediante gnu paralelo para utilizar simultáneamente todos los núcleos de mi i7 :).
Aquí está el código real de Python que escribí para resolver el problema de ejemplo que publiqué. Uno podría pegarlo directamente después del final del código en la pregunta.
Déjame decirte que es realmente algo cuando ves que todos los núcleos se disparan al máximo ruido :). Un agradecimiento especial a Ole y al equipo que construyó Gnu Parallel.
Sería bueno tener una solución multiplataforma y sería bueno si hubiera podido descifrar el módulo de multiprocesamiento de Python para el qgis Python incrustado, pero desafortunadamente no fue así.
Independientemente, esta solución me servirá y quizás a usted muy bien.
fuente