Please activate JavaScript!
Please install Adobe Flash Player, click here for download

arcAKTUELL 1.2014 - Wertvoll und begehrt

41t ipps u nd t ric k s 41 Bei der Anwendung von Geoverarbeitungswerkzeugen stellt man im- mer wieder fest, dass nicht alle Systemressourcen (CPU, RAM, …) voll- ständig ausgeschöpft werden. Während man dies auf der einen Seite begrüßt, weil man in der Zwischenzeit auch noch andere Dinge am Sys- tem erledigen kann, wünscht man sich vor allem bei Prozessen mit sehr langen Laufzeiten wegen großer Datenmengen oder sehr vieler einzel- ner Datensätze eher eine Beschleunigung der Verarbeitung durch die Nutzung aller verfügbarer Ressourcen. Die in Python integrierten Module thread und multiprocessing bie- ten ohne zusätzliche Installationen die Möglichkeit, Geoverarbeitungs- prozesse durch Parallelisierung zu beschleunigen, wobei der Grad der Beschleunigung sehr stark von den einzelnen Aufgabenstellungen abhängt. Dabei ist zu beachten, dass mit der Parallelisierung ein zu- sätzlicher zeitlicher Overhead verbunden ist. Er resultiert zum einen aus dem Entwicklungsaufwand – in der Regel gleichen die Arbeiten einem „Trial and error“-Szenario, bis die optimale Partitionierung gefun- den ist – und zum anderen aus zusätzlichem Rechenaufwand. Er entsteht dadurch, dass die zu verarbeitenden Daten für die einzelnen Jobs vor- konfektioniert und am Schluss die Teilergebnisse der einzelnen Prozesse wieder zu einem Gesamtresultat zusammengeführt werden müssen. Dazu kommt, dass bei jedem neuen Prozess („out of process“) die Geo- verarbeitungsumgebung jeweils neu initialisiert werden muss, was bei einer Verarbeitung „in process“ nicht erforderlich ist. Dieser Overhead kann nur dadurch kompensiert werden, dass die Zeitersparnis durch die Parallelisierung den Aufwand der Konfektionierung und Initialisierung mehr als nur ausgleicht und der Entwicklungsaufwand durch die häu- fige, am besten regelmäßige Verwendung der Geoverarbeitungswerk- zeuge gerechtfertigt werden kann. Was die Teilergebnisse einzelner Prozesse betrifft, so ist die Nutzung einer gemeinsamen prozessübergreifenden Geodatabase im Allgemeinen nicht möglich. Beim Anlegen von neuen Tabellen in der Geodatabase wird sie von einem der Prozesse exklusiv gesperrt (schema lock), sodass andere Prozesse an dieser Stelle scheitern. In diesem Fall muss in einem temporären Verzeichnis für jeden Prozess eine prozesseigene File-Geodatabase erzeugt werden. Nur wenn eine derartige Schema­ änderung in der Datenbank nicht erforderlich ist und Daten von paral- lelen Prozessen in vorhandene Tabellen geschrieben werden, ist eine Multiuser- bzw. ArcSDE Geodatabase nutzbar. Zwischenergebnisse soll- ten aus Performancegründen immer in einer „in_memory“ Geodatabase zwischengespeichert werden. Um Out-of-Memory-Probleme zu ver­ meiden, sollte an jedem Prozessende die „in_memory“ Geodatabase explizit gelöscht werden. Löschen einer „in_memory“ Geodatabase: arcpy.Delete_management(„in_memory“) Wie schon erwähnt funktioniert das Multiprocessing in ArcGIS nur out of process. Das bedingt, dass bei den Eigenschaften eines Skript Tools, das im referenzierten Python-Skript das Multiprocessing-Modul nutzt, der Haken bei „Run Python script in process“ nicht gesetzt werden darf. Multithreading wiederum ist in-process-fähig, wird aber durch das Geo- processing-Framework direkt nicht unterstützt. Multithreading mit Geo- processing funktioniert deshalb nur in Verbindung mit dem Subprocess- Modul, bei dem jeder Thread seinen Job in einen eigenen Prozess aus- lagert und so lange wartet, bis dieser – wiederum out of process – seine Aufgabe erledigt hat. Das setzt bei der Implementierung allerdings voraus, dass der Code für die einzelnen Jobs in ein eigenes Python- Skript ausgelagert werden muss. Wie viele Jobs und Prozesse sind eigentlich ideal? Die Anzahl der Pro- zesse, die gleichzeitig Jobs bearbeiten, ist optimal, wenn alle System- ressourcen über den gesamten Verarbeitungszeitraum ausgeschöpft werden können. Wenn es möglich ist, die zu verarbeitenden Daten so gleichmäßig aufzuteilen, dass jeder Job in etwa gleich lange arbeitet, ist pro Job ein Prozess und ein Prozess pro CPU ideal. Anzahl der CPUs in Python: noOfJobs = multiprocessing.cpu_count() Viele kleine Jobs würden in diesem Fall einen zusätzlichen und unnötigen Overhead bewirken. Können die Daten allerdings nur zufällig und hetero- genaufdieJobsverteiltwerden(zumBeispieldurchdieVerwendungeines regelmäßigen räumlichen Gitters), sind vielleicht 3 oder 4 Jobs pro CPU günstiger; ansonsten läuft man Gefahr, dass einer dieser Prozesse sehr schnell beendet ist und ein anderer aber sehr lange dauern kann – und in der Zwischenzeit die Ressourcen des ersten nicht weiter genutzt werden. Haben Sie also eine zu verarbeitende Objektliste auf der einen Seite und 4 CPUs für die Verarbeitung auf der anderen Seite, könnte es eine gute Strategie sein, die Objektliste (zum Beispiel OIDs 1 bis 100000) in 4 gleich große Objektlisten (OIDs 1 bis 25000, 25001 bis 50000, 50001 bis 75000, 75001 bis 100000) aufzuteilen und 4 Jobs – einer pro Liste – zu definieren, die gleichzeitig mit 4 Prozessen abgearbeitet werden. Haben Sie 4 CPUs und Daten, die über ein großes Gebiet verteilt sind, hat es unter Umständen Sinn, sie räumlich mithilfe eines Gitters aufzu- teilen. Jedes Gitter wird durch einen Job verarbeitet. Da die Menge der Daten pro Job aber in der Regel unterschiedlich groß ist, könnte es hier eine gute Strategie sein, mehr als nur 4 Jobs zu definieren: ein Gitter mit 16 Flächen definiert 16 Jobs, die durch 4 gleichzeitige Prozesse abge- arbeitet werden. Während ein Prozess dann einen Job mit sehr vielen Daten verarbeitet, kann ein anderer Prozess in dieser Zeit mehrere Jobs mit weniger Daten prozessieren. Entsprechend einer dieser gewählten Verteilstrategien (gleichmäßig oder zufällig) wählt man in Python die dazu passende Implementie- rung. Können die Daten gleichmäßig auf so viele Jobs wie verfügbare CPUs verteilt werden, ist die Thread- oder die Multiprocessing.Process- Strategie am geeignetsten, bei denen jeder Job gezielt einem Prozess zugeordnet wird. Definiert man viele kleine Jobs, ist die Multiprocessing. Pool-Implementierung die effektivste, weil hier die Jobs dynamisch den Prozessen zugewiesen werden: Hat ein Prozess einen Job abgearbeitet, wird ihm automatisch ein neuer Job zugewiesen. Die Thread-Strategie sieht vor, dass das Python-Script (Dispatcher) pro Job einen Thread startet. Sobald die Threads gestartet (multithreading. start_new_thread) wurden, läuft das Script durch eine While-Schleife, bis sich alle Threads wieder zurückgemeldet haben (num_threads = 0): TIPPS UND TRICKS Für Anwender Beschleunigte Geoverarbeitung durch Multiprocessing/ Multithreading in ArcGIS for Desktop

Seitenübersicht