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?
quelle
Antworten:
Wenn Sie Ihr Programm so ändern, dass es den Dateinamen von der Befehlszeile liest und Ihre Eingabedatei in kleinere Teile aufteilt, können Sie mit GNU Parallel Folgendes tun:
Dadurch wird 1 Job pro Kern ausgeführt.
Alle neuen Computer haben mehrere Kerne, aber die meisten Programme sind serieller Natur und verwenden daher nicht die mehreren Kerne. Viele Aufgaben sind jedoch extrem parallelisierbar:
GNU Parallel ist ein allgemeiner Parallelisierer, mit dem Sie auf einfache Weise Jobs auf demselben Computer oder auf mehreren Computern, auf die Sie ssh-Zugriff haben, parallel ausführen können.
Wenn Sie 32 verschiedene Jobs auf 4 CPUs ausführen möchten, können Sie auf einfache Weise 8 Jobs auf jeder CPU parallelisieren:
GNU Parallel erzeugt stattdessen einen neuen Prozess, wenn man fertig ist - die CPUs aktiv zu halten und damit Zeit zu sparen:
Installation
Wenn GNU Parallel nicht für Ihre Distribution gepackt ist, können Sie eine persönliche Installation durchführen, für die kein Root-Zugriff erforderlich ist. Dies kann in 10 Sekunden geschehen:
Weitere Installationsoptionen finden Sie unter http://git.savannah.gnu.org/cgit/parallel.git/tree/README
Erfahren Sie mehr
Weitere Beispiele finden Sie unter: http://www.gnu.org/software/parallel/man.html
Sehen Sie sich die Intro-Videos an: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Gehen Sie durch das Tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html
Melden Sie sich für die E-Mail-Liste an, um Unterstützung zu erhalten: https://lists.gnu.org/mailman/listinfo/parallel
quelle
my_processing.py
finden Sie unter gis.stackexchange.com/a/130337/26897Anstatt die GNU Parallel-Methode zu verwenden, können Sie das Python- Multiprozess- Modul verwenden, um einen Pool von Tasks zu erstellen und diese auszuführen. Ich habe keinen Zugriff auf ein QGIS-Setup, um es zu testen, aber in Python 2.6 wurde Multiprocess hinzugefügt, vorausgesetzt, dass Sie 2.6 oder höher verwenden, sollte es verfügbar sein. Es gibt viele Online-Beispiele zur Verwendung dieses Moduls.
quelle
Hier ist die Gnu-Parallellösung. Mit einiger Sorgfalt könnten die meisten auf Linux basierenden Parallel-Ogr- oder -Saga-Algorithmen so erstellt werden, dass sie in Ihrer QGIS-Installation ausgeführt werden.
Offensichtlich erfordert diese Lösung die Installation von gnu parallel. Um gnu parallel in Ubuntu zu installieren, gehen Sie zum Beispiel zu Ihrem Terminal und geben Sie Folgendes ein
NB: Ich konnte den parallelen Shell-Befehl nicht in Popen oder Subprozessen ausführen, was mir lieber gewesen wäre. Deshalb habe ich einen Export in ein Bash-Skript gehackt und diesen stattdessen mit Popen ausgeführt.
Hier ist der spezielle Shell-Befehl, der parallele Befehle verwendet, die ich in Python eingebunden habe
Jede {1} wird gegen eine Zahl aus dem Bereich {1..400} ausgetauscht, und dann werden die vierhundert Shell-Befehle von gnu parallel verwaltet, um alle Kerne meines i7 :) gleichzeitig zu verwenden.
Hier ist der eigentliche Python-Code, den ich geschrieben habe, um das Beispielproblem zu lösen, das ich veröffentlicht habe. Man könnte es direkt nach dem Ende des Codes in die Frage einfügen.
Lass mich dir sagen, dass es wirklich etwas ist, wenn du siehst, wie alle Kerne auf vollen Touren laufen :). Besonderer Dank geht an Ole und das Team, das Gnu Parallel gebaut hat.
Es wäre schön, eine plattformübergreifende Lösung zu haben, und es wäre schön, wenn ich das Multiprozessor-Python-Modul für das in qgis eingebettete Python hätte herausfinden können, aber leider sollte es nicht so sein.
Unabhängig davon wird diese Lösung mir und vielleicht auch Ihnen guttun.
quelle