Optimierung des Python-Codes für Big Data

34

Ich habe Python-Code, der so konzipiert ist, dass er Punkt-Shapefiles durch den folgenden Workflow nimmt:

  1. Punkte zusammenführen
  2. Integrieren Sie Punkte so, dass alle Punkte innerhalb von 1 m zu einem Punkt werden
  3. Feature-Layer erstellen, in dem Punkte mit z <10 ausgewählt werden
  4. Pufferpunkte
  5. Polygon bis Raster 1 m Auflösung
  6. Reklassifizieren, wobei 1 - 9 = 1; NoData = 0

Jedes Shapefile hat ungefähr 250.000 bis 350.000 Punkte auf einer Fläche von ca. 5 x 7 km. Als Eingaben verwendete Punktdaten repräsentieren Baumpositionen. Jedem Punkt (dh Baum) ist ein "z" -Wert zugeordnet, der den Kronenradius darstellt und im Pufferprozess verwendet wird. Ich beabsichtige, die endgültige Binärausgabe in einem separaten Prozess zu verwenden, um ein Raster zu erstellen, das die Überdachung beschreibt.

Ich habe einen Test mit vier Shapefiles durchgeführt und dabei ein Raster von 700 MB erstellt. Der Test dauerte 35 Minuten (i5-Prozessor und 8 GB RAM). Da ich diesen Prozess für 3500 Shapefiles ausführen muss, würde ich mich über jeden Rat freuen, um den Prozess zu rationalisieren (siehe beigefügten Code). Was ist im Allgemeinen der beste Weg, um mit der Geoverarbeitung von Big Data umzugehen? Gibt es irgendwelche Änderungen am Code oder Workflow, die zur Steigerung der Effizienz beitragen könnten?

Bearbeiten :

Zeit (% der Gesamtsumme) für Geoverarbeitungsaufgaben:

  • Zusammenführung = 7,6%
  • Integrieren = 7,1%
  • Merkmal zu Lyr = 0
  • Puffer = 8,8%
  • Poly zu Raster = 74,8%
  • Reklassifizieren = 1,6%

Bildbeschreibung hier eingeben

# Import arcpy module
import arcpy

# Check out any necessary licenses
arcpy.CheckOutExtension("spatial")

# Script arguments
temp4 = arcpy.GetParameterAsText(0)
if temp4 == '#' or not temp4:
    temp4 = "C:\\gdrive\\temp\\temp4" # provide a default value if unspecified

Reclassification = arcpy.GetParameterAsText(1)
if Reclassification == '#' or not Reclassification:
    Reclassification = "1 9 1;NODATA 0" # provide a default value if unspecified

Multiple_Value = arcpy.GetParameterAsText(2)
if Multiple_Value == '#' or not Multiple_Value:
    Multiple_Value = "C:\\t1.shp;C:\\t2.shp;C:\\t3.shp;C:\\t4.shp" # provide a default value if unspecified

# Local variables:
temp_shp = Multiple_Value
Output_Features = temp_shp
temp2_Layer = Output_Features
temp_Buffer = temp2_Layer
temp3 = temp_Buffer

# Process: Merge
arcpy.Merge_management(Multiple_Value, temp_shp, "x \"x\" true true false 19 Double 0 0 ,First,#,C:\\#########omitted to save space

# Process: Integrate
arcpy.Integrate_management("C:\\gdrive\\temp\\temp.shp #", "1 Meters")

# Process: Make Feature Layer
arcpy.MakeFeatureLayer_management(temp_shp, temp2_Layer, "z <10", "", "x x VISIBLE NONE;y y VISIBLE NONE;z z VISIBLE NONE;Buffer Buffer VISIBLE NONE")

# Process: Buffer
arcpy.Buffer_analysis(temp2_Layer, temp_Buffer, "z", "FULL", "ROUND", "NONE", "")

# Process: Polygon to Raster
arcpy.PolygonToRaster_conversion(temp_Buffer, "BUFF_DIST", temp3, "CELL_CENTER", "NONE", "1")

# Process: Reclassify
arcpy.gp.Reclassify_sa(temp3, "Value", Reclassification, temp4, "DATA")
Aaron
quelle
3
Es kann sich lohnen, einen Performance-Timing-Code einzugeben, um festzustellen, ob der Großteil der Zeit in einen oder mehrere Schritte
fließt
5
Ich glaube, Sie haben nicht viele Möglichkeiten, die Leistung zu verbessern, wenn Sie weiterhin ArcPy verwenden. Vielleicht können Sie sich andere Tools ansehen, um dies zu tun? Tools wie FME oder vielleicht Postgis?
tmske
3
Es ist nicht klar, welcher Pixeltyp verwendet wird, aber wenn es "Byte" ist (was es sein sollte), dann wäre der Rohdatenspeicher 5000x7000 = 35 MB (~ 33,4 MB) pro Raster, was eigentlich nicht so groß ist. Die nächste Dimension von 3500 (Zeitdimension?) Erhöht jedoch die Gesamt-Raw-Größe auf ~ 114 GB.
Mike T
5
Obwohl ich aus dieser Beschreibung nicht erkennen kann, was der Algorithmus tut (oder beabsichtigt), sollten in den meisten Fällen Punktpuffer, denen eine Rasterisierung folgt, durch eine Rasterisierung der Punkte gefolgt von einer Fokusstatistik (normalerweise ein Mittelwert oder eine Summe) ersetzt werden. Das Ergebnis wird dasselbe sein, aber durch Vermeiden der langwierigen Pufferungs- und Polyrasterisierungsschritte wird es viel schneller erhalten. Ich vermute (stark), dass erhebliche zusätzliche Beschleunigungen erzielt werden könnten, kann aber aufgrund der vagen Beschreibung des Verfahrens keine spezifischen Ratschläge erteilen.
whuber
2
Die Puffer um die Punkte haben eine variable Größe (basierend auf dem z-Wert des Punkts). Wenn Sie weiterhin Fokusstatistiken erstellen möchten, müssen Sie die Ergebnispunkte durch den Z-Wert aufteilen und Raster- und Fokusstatistiken für jeden Satz erstellen (wobei Z als Radius für eine kreisförmige Umgebung mit Maximum als Statistik verwendet wird). Führen Sie anschließend die Zellstatistik über alle 9 Raster mit der maximalen Statistik aus, um die Ergebnisse miteinander zu kombinieren. (Was wahrscheinlich immer noch viel schneller ist als puffern und rastern mit einem großen Datensatz.)
blord-castillo

Antworten:

10

Einige Algorithmusänderungen, die Ihnen helfen sollten.

Führen Sie Ihre Auswahl zuerst vor dem Zusammenführen oder Integrieren aus. Dies reduziert die späteren Funktionen, die am teuersten sind, erheblich.

Zusammenführen und Integrieren sind beide speicherintensiv. Sie möchten also weiterhin Features entfernen, während Sie Feature-Classes einbinden, und versuchen, Ihre Zusammenführungen in einer Binärstruktur vorzunehmen, um die Größe der Zusammenführungen und Integrierungen gering zu halten. zB für vier Shapefiles werden zwei Shapefiles zusammengeführt und integriert; zwei weitere Shapefiles zusammenführen und integrieren; Führen Sie die beiden resultierenden Feature-Classes zusammen und integrieren Sie sie.

Ihre Jobwarteschlange beginnt als Warteschlange mit Shapefile-Referenzen. Sie haben auch eine Ergebniswarteschlange, in die die Ergebnisse gestellt werden können. Die run () -Methode für Ihren Parallelverarbeitungs-Worker führt die folgenden Vorgänge aus: Entfernen Sie zwei Elemente aus der Warteschlange. Wenn kein Artikel entnommen wurde (die Warteschlange ist leer), beenden Sie den Worker. Wenn ein Objekt belegt ist, legen Sie dieses Objekt direkt in die Ergebniswarteschlange.

Wenn für jedes Element zwei Elemente verwendet werden: Wenn es sich um ein Shapefile handelt, wählen Sie z <10 aus, und erstellen Sie eine Feature-Class in_memory. Andernfalls ist es bereits eine in_memory-Feature-Class und überspringt den Auswahlschritt. Führen Sie die beiden in_memory-Feature-Classes zusammen, um eine neue in_memory-Feature-Class zu erstellen. Löschen Sie die beiden ursprünglichen Feature-Classes. Führen Sie "Integrieren" für die neue Feature-Class aus. Fügen Sie diese Feature-Class in die Ergebniswarteschlange ein.

Führen Sie dann eine äußere while-Schleife aus. Die Schleife beginnt mit der Shapefile-Warteschlange und prüft, ob die Länge größer als 1 ist. Anschließend führt sie die Warteschlange durch die Worker. Wenn die Länge der Ergebniswarteschlange größer als 1 ist, führt die while-Schleife eine weitere parallele Verarbeitung durch, bis die Ergebniswarteschlange die Feature-Class 1 in_memory hat.

Beispiel: Wenn Sie mit 3500 Shapefiles beginnen, enthält Ihre erste Warteschlange 3500 Jobs. Zweiter wird 1750 Arbeitsplätze haben. 875, 438, 219, 110, 55, 28, 14, 7, 4, 2, 1. Ihr großer Engpass wird das Gedächtnis sein. Wenn Sie nicht über genügend Arbeitsspeicher verfügen (und wenn dies der Fall ist, wird beim Erstellen der ersten Ergebniswarteschlange nicht genügend Arbeitsspeicher zur Verfügung stehen), ändern Sie Ihren Algorithmus so, dass mehr als 2 Feature-Classes gleichzeitig zusammengeführt und dann integriert werden, was zu einer Verringerung führt Die Größe Ihrer ersten Ergebniswarteschlange im Gegenzug für eine längere Verarbeitungszeit. Optional können Sie Ausgabedateien schreiben und mithilfe der Feature-Classes in_memory überspringen. Dies wird Sie erheblich verlangsamen, würde aber den Speicherengpass überwinden.

Erst nachdem Sie alle Shapefiles zusammengeführt und integriert haben und mit einer einzigen Feature-Class enden, führen Sie den Puffer, das Poly-to-Raster und die Neuklassifizierung durch. Auf diese Weise werden diese drei Vorgänge nur einmal ausgeführt und Sie behalten Ihre Geometrie einfach bei.

Blord-Castillo
quelle
+1 für die Verwendung des Arbeitsbereichs in_memory, wenn Ihre Daten in den Speicher passen. Dadurch werden Geoverarbeitungsvorgänge erheblich beschleunigt.
RyanDalton
Das ist gutes Zeug. Ich denke, mit einem Diagramm und etwas Pseudocode (oder echtem Code!) Könnte es sogar noch besser sein.
blah238
Ja, ich wünschte, ich hätte etwas Zeit, um mich auf den Code einzulassen. Ich muss sowieso ein neues Parallelverarbeitungs-Demo-Skript schreiben.
Blord-Castillo
14

Mit so etwas wie das erste , was ich tun würde , ist Ihr System Ressourcenauslastung überwachen Ressourcenmonitor in Windows 7 oder perfmon in Vista / XP ein Gefühl dafür zu bekommen , ob Sie CPU -, Speicher - oder IO-gebunden .

Wenn Sie an Arbeitsspeicher oder E / A gebunden sind, können Sie wahrscheinlich nur die Hardware aktualisieren, die Problemgröße verringern oder den Ansatz vollständig ändern.

Wenn Sie feststellen, dass Sie CPU-gebunden sind, würde ich mit dem multiprocessingModul oder einem der vielen anderen verfügbaren Python-basierten Parallelverarbeitungspakete experimentieren, um festzustellen, ob Sie mehr CPU-Kerne verwenden können, um Ihre Vorgänge zu beschleunigen.

Der Trick für Multiprocessing und Parallelität im Allgemeinen besteht darin, ein gutes Partitionsschema zu finden, das:

  1. Ermöglicht die Aufteilung der Eingaben in kleinere Arbeitssätze und anschließende sinnvolle Neukombination der Ergebnisse.
  2. Fügt den geringsten Overhead hinzu (einige sind im Vergleich zur seriellen Verarbeitung unvermeidbar) und
  3. Ermöglicht die Anpassung der Größe des Arbeitssets, um die Systemressourcen für eine optimale Leistung optimal zu nutzen.

Sie können das Skript, das ich in dieser Antwort erstellt habe, als Ausgangspunkt verwenden: Porting Avenue-Code zum Erstellen von Schatten für ArcPy / Python for ArcGIS Desktop?

Siehe auch diesen Blogeintrag zu ESRI Geoprocessing zum Thema: Python Multiprocessing - Ansätze und Überlegungen

Ich denke, dass Ihr Fall aufgrund der "Black Box" -Natur der verwendeten Werkzeuge und nicht der feinkörnigeren Geometriearrays, mit denen ich gearbeitet habe, noch herausfordernder wird. Vielleicht kann es nützlich sein , mit NumPy- Arrays zu arbeiten .

Ich habe auch interessantes Lesematerial gefunden, wenn Sie über arcpy hinausblicken wollten:

blah238
quelle