Eine häufige Anforderung in GIS besteht darin, ein Verarbeitungswerkzeug auf eine Reihe von Dateien anzuwenden oder einen Prozess für eine Reihe von Features in einer Datei auf eine andere Datei anzuwenden.
Viele dieser Operationen sind insofern peinlich parallel, als die Ergebnisse der Berechnungen keinen Einfluss auf andere Operationen in der Schleife haben. Nicht nur das, sondern auch die Eingabedateien sind oft unterschiedlich.
Ein klassisches Beispiel hierfür ist das Kacheln von Formdateien mit Dateien, die Polygone enthalten, um sie zu kürzen.
Hier ist eine (getestete) klassische prozedurale Methode, um dies in einem Python-Skript für QGIS zu erreichen. (Für die Ausgabe von temporären Speicherdateien in echte Dateien wurde die Zeit für die Verarbeitung meiner Testdateien mehr als halbiert.)
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())
Dies wäre in Ordnung, außer dass meine Eingabedatei 2 GB groß ist und die Polygon-Clipping-Datei mehr als 400 Polygone enthält. Der resultierende Prozess dauert auf meinem Quad-Core-Rechner über eine Woche. Währenddessen laufen drei Kerne nur im Leerlauf.
Die Lösung, die ich in meinem Kopf habe, besteht darin, den Prozess in Skriptdateien zu exportieren und sie asynchron auszuführen, zum Beispiel mit gnu parallel. Es scheint jedoch eine Schande zu sein, QGIS in einer betriebssystemspezifischen Lösung beenden zu müssen, anstatt etwas zu verwenden, das ursprünglich für QGIS-Python gedacht ist. Meine Frage lautet also:
Kann ich peinlich parallele geografische Operationen nativ in Python QGIS parallelisieren?
Wenn nicht, hat vielleicht schon jemand den Code, um diese Art von Arbeit an asynchrone Shell-Skripte zu senden?