Leistung von ArcGISScripting und großen Geodatensätzen

38

Momentan schreibe ich ein Python-Skript mit dem arcgisscripting-Modul, um einen relativ großen Datensatz (insgesamt ~ 10.000 Datensätze) zu verarbeiten, der über eine kleine Anzahl von Tabellen normalisiert ist, insgesamt 8. Der Prozess besteht aus der Erstellung eines Features basierend auf Koordinatentupeln (x, y) und der Erstellung eines Diagramms (Knoten und Linien) unter Verwendung der Beziehungen in den anderen 7 Tabellen zur Orientierung. Die endgültige Ausgabe ist eine Personal Geodatabase (pgdb / fgdb) mit Geodatensätzen für Knoten und Kanten, die die Beziehungen visuell darstellen.

Mein erster Versuch bestand darin, Abfragen der neuen Geodatabase-Tabellen und SearchCursor-Datensatzgruppen zu verwenden, um Verknüpfungstabellen (InsertCursor) für die auftretenden Viele-zu-Viele-Beziehungen aufzufüllen. Dies hat sehr gut funktioniert, bis auf die 15-20 Minuten Bearbeitungszeit.

Bei Verwendung des cProfiler-Moduls in Python stellte sich heraus, dass das 'Thrashen' einer Personal Geodatabase beim Durchführen der Suchabfragen zum Auffüllen der Verknüpfungstabellen mit Anforderungen für Cursor (Suchen und Einfügen von Cursorn) die erschreckende Leistung verursachte.

Mit ein wenig Umgestaltung habe ich es geschafft, die Bearbeitungszeit unter 2,5 Minuten zu bekommen. Der Kompromiss bestand in der teilweisen Erstellung des Geodatabase-Schemas im Code und der Beschränkung der Anforderungen für ArcGisscript-Cursor auf InsertCursors, sobald alle Beziehungen sortiert waren.

Meine Frage ist eine der Leistung;

  • Mit welchen Techniken haben die Mitarbeiter bei der Arbeit mit großen Datenmengen angemessene Rechenzeiten eingehalten?
  • Gibt es von ESRI empfohlene Methoden, die ich bei meiner Suche nach Optimierung verpasst habe?

    Ich verstehe den Aufwand, der beim Erstellen eines Arcgisscripting-Cursors anfällt, insbesondere, wenn er aus einer persönlichen Geodatabase stammt. Nach einer langen Suche nach leistungsbezogenen Antworten von dieser Website und von Google habe ich jedoch den Eindruck, dass die Leistung nicht im Vordergrund der Bemühungen der Menschen steht .

  • Erwartet und duldet man als Anwender von ESRI-Produkten diese Leistungsverzögerungen?

AKTUALISIEREN

Nach einigen Arbeiten mit diesem Produkt habe ich eine Liste von Optimierungstechniken zusammengestellt, bei denen räumliche Informationen aus einem ordnungsgemäßen Format in eine Geodatabase konvertiert wurden. Dies wurde für die Geodatabase "Personal" und "File" entwickelt. Leckerbissen:

  1. Lesen Sie Ihre Daten und rationalisieren Sie sie im Speicher. Dies halbiert Ihre Zeit.

  2. Erstellen Sie Feature-Classes und Tabellen im Speicher. Verwenden Sie das Feature-Dataset-Keywork 'in_memory', um Ihren Speicher als RAM-Disk zu verwenden, Ihre Funktionen dort auszuführen und dann auf die Festplatte zu schreiben

  3. Verwenden Sie zum Schreiben auf die Festplatte die CopyFeature-Klasse für Feature-Classes und CopyRow für Tabellen.

Diese drei Dinge erforderten ein Skript, das über 100.000 Features von 30 Minuten auf 30 bis 40 Sekunden in eine Geodatabase konvertierte, einschließlich Beziehungsklassen. Sie sollten nicht leichtfertig verwendet werden. Die meisten der oben genannten Methoden verbrauchen viel Speicher, was zu Problemen führen kann, wenn Sie nicht aufpassen.

OptimizePrime
quelle
1
Haben Sie versucht, ein anderes Speicherformat zu verwenden? Wie funktioniert eine File-Geodatabase?
Derek Swingley
Eine File-Geodatabase weist eine etwas schlechtere Leistung auf als eine Personal-Geodatabase. Ich habe gestern eine ArcSDE-Instanz eingerichtet und optimiert, um die Leistung in einem Unternehmensformat zu testen. Ich werde Sie über meine Ergebnisse
OptimizePrime
2
Das hilft Ihnen jetzt nicht weiter, aber in 10.1 wurde die Cursorleistung in Python durch das neue Datenzugriffsmodul um einen großen Faktor verbessert (im Durchschnitt in der Größenordnung).
Jason Scheirer
In_memory verwendet den InMemoryWorkspace edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriDataSourcesGDB/… , der nach einer beliebigen Anzahl von Zeilen alles in eine ScratchWorkspaceFactory (dh FileGDB) kopiert und sich auf FileGDB verlässt, um die gesamte Arbeit zu erledigen
Ragi Yaser Burhum

Antworten:

56

Obwohl diese Frage bereits beantwortet wurde, dachte ich, ich könnte meine zwei Cent einlösen.

HAFTUNGSAUSSCHLUSS : Ich habe einige Jahre für ESRI im GeoDatabase-Team gearbeitet und war für die Verwaltung verschiedener Teile des GeoDatabase-Codes (Versionierung, Cursors, EditSessions, Verlauf, Beziehungsklassen usw. usw.) verantwortlich.

Ich denke, die größte Ursache für Leistungsprobleme mit ESRI-Code ist, dass man die Auswirkungen der Verwendung verschiedener Objekte nicht versteht, insbesondere die "kleinen" Details der verschiedenen GeoDatabase-Abstraktionen! Sehr oft wechselt die Konversation zu der Sprache, die als Täter für die Leistungsprobleme verwendet wird. In einigen Fällen kann es sein. Aber nicht die ganze Zeit. Beginnen wir mit der Sprachdiskussion und arbeiten uns zurück.

1.- Die Programmiersprache, die Sie auswählen, spielt nur eine Rolle, wenn Sie komplizierte Aufgaben in einer engen Schleife ausführen. Meistens ist dies nicht der Fall.

Der große Elefant im Raum ist, dass Sie im Kern des gesamten ESRI-Codes ArcObjects haben - und ArcObjects mit COM in C ++ geschrieben wurde . Die Kommunikation mit diesem Code ist kostenpflichtig. Dies gilt für C #, VB.NET, Python oder was auch immer Sie verwenden.

Sie zahlen einen Preis bei der Initialisierung dieses Codes. Dies kann zu vernachlässigbaren Kosten führen, wenn Sie dies nur einmal tun.

Sie zahlen dann einen Preis für jede weitere Interaktion mit ArcObjects.

Persönlich neige ich dazu, Code für meine Kunden in C # zu schreiben, weil es einfach und schnell genug ist. Jedes Mal, wenn ich Daten verschieben oder eine Verarbeitung für große Datenmengen durchführen möchte, die bereits in der Geoverarbeitung implementiert sind, initialisiere ich einfach das Skriptsubsystem und übergebe meine Parameter. Warum?

  • Es ist bereits implementiert. Warum also das Rad neu erfinden?
  • Es kann tatsächlich schneller sein . "Schneller als in C # schreiben?" Ja! Wenn ich das Laden von Daten beispielsweise manuell implementiere, bedeutet dies, dass ich den Preis für die .NET-Kontextumschaltung in einer engen Schleife zahle. Für jedes GetValue, Insert und ShapeCopy fallen Kosten an. Wenn ich den einen Aufruf in GP durchführe, geschieht der gesamte Datenladeprozess in der tatsächlichen Implementierung von GP - in C ++ innerhalb der COM-Umgebung. Ich zahle nicht den Preis für Kontextwechsel, weil es keine gibt - und daher ist es schneller.

Ah ja, also dann die Lösung, wenn viele Geoverarbeitungsfunktionen verwendet werden sollen. Eigentlich muss man vorsichtig sein.

2. GP ist eine Blackbox, die Daten (möglicherweise unnötig) kopiert

Es ist ein zweischneidiges Schwert. Es handelt sich um eine Black Box, die intern etwas zaubert und Ergebnisse ausspuckt - aber diese Ergebnisse werden sehr oft dupliziert. 100.000 Zeilen können problemlos in 1.000.000 Zeilen auf der Festplatte konvertiert werden, nachdem Sie Ihre Daten über 9 verschiedene Funktionen ausgeführt haben. Die Verwendung von GP-Funktionen entspricht der Erstellung eines linearen GP-Modells.

3. Die Verkettung zu vieler GP-Funktionen für große Datenmengen ist äußerst ineffizient. Ein GP-Modell ist (potentiell) gleichbedeutend mit einer wirklich sehr, sehr dummen Ausführung einer Abfrage

Versteh mich jetzt nicht falsch. Ich liebe GP Models - das erspart mir das ständige Schreiben von Code. Mir ist aber auch bewusst, dass es nicht die effizienteste Art ist, große Datensätze zu verarbeiten.

Haben Sie schon einmal von einem Abfrageplaner gehört ? Ihre Aufgabe ist es, die SQL-Anweisung zu überprüfen, die Sie ausführen möchten, einen Ausführungsplan in Form eines gerichteten Diagramms zu generieren , das einem GP-Modell sehr ähnlich sieht , die in der Datenbank gespeicherten Statistiken zu überprüfen und die meisten auszuwählen optimale Reihenfolge, um sie auszuführen . GP führt sie nur in der Reihenfolge aus, in der Sie sie abgelegt haben, weil es keine Statistiken gibt, mit denen Sie intelligenter vorgehen können - Sie sind der Abfrageplaner . Und rate was? Die Reihenfolge, in der Sie die Dinge ausführen, hängt stark von Ihrem Datensatz ab. Die Reihenfolge, in der Sie die Dinge ausführen, kann den Unterschied zwischen Tagen und Sekunden ausmachen, und die Entscheidung liegt bei Ihnen.

"Großartig", sagst du, ich schreibe die Dinge nicht selbst und achte darauf, wie ich Sachen schreibe. Aber verstehen Sie GeoDatabase-Abstraktionen?

4.Unverständliche GeoDatabase-Abstraktionen können Sie leicht beißen

Anstatt auf jede einzelne Sache hinzuweisen, die Ihnen möglicherweise Probleme bereiten kann, möchte ich auf einige häufige Fehler hinweisen, die ich ständig sehe, sowie auf einige Empfehlungen.

  • Verstehen des Unterschieds zwischen True / False für das Recycling von Cursorn . Dieses winzige kleine Flag, das auf true gesetzt ist, kann die Laufzeit um Größenordnungen beschleunigen.
  • Versetzen Sie Ihre Tabelle in LoadOnlyMode für Datenladevorgänge . Warum sollte der Index für jede Beilage aktualisiert werden?
  • Verstehen Sie, dass IWorkspaceEdit :: StartEditing zwar in allen Arbeitsbereichen gleich aussieht, es sich jedoch bei jeder Datenquelle um sehr unterschiedliche Bestien handelt. In einer Enterprise GDB verfügen Sie möglicherweise über eine Versionierung oder Unterstützung für Transaktionen. In Shapefiles muss es auf eine ganz andere Art und Weise implementiert werden. Wie würden Sie Undo / Redo implementieren? Müssen Sie es überhaupt aktivieren (ja, es kann sich auf die Speichernutzung auswirken)?
  • Der Unterschied zwischen Stapeloperationen oder Einzelzeilenoperationen. Fallbeispiel GetRow vs GetRows - Dies ist der Unterschied zwischen einer Abfrage, um eine Zeile abzurufen, oder einer Abfrage, um mehrere Zeilen abzurufen. Eine enge Schleife mit dem Aufruf von GetRow bedeutet schreckliche Leistung und ist der Hauptgrund für Leistungsprobleme
  • Verwenden Sie UpdateSearchedRows
  • Verstehen Sie den Unterschied zwischen CreateRow und CreateRowBuffer . Enormer Unterschied in der Insert-Laufzeit.
  • Verstehen Sie, dass IRow :: Store und IFeature :: Store extrem schwere polymorphe Operationen auslösen . Dies ist wahrscheinlich der Grund # 2 für die sehr langsame Leistung. Es wird nicht nur die Zeile gespeichert. Mit dieser Methode wird sichergestellt, dass Ihr geometrisches Netzwerk in Ordnung ist. Der ArcMap-Editor wird darüber informiert, dass sich eine Zeile geändert hat. Außerdem werden alle Beziehungsklassen benachrichtigt, die etwas mit dieser Zeile zu tun haben Stellen Sie sicher, dass die Kardinalität gültig ist usw. Sie sollten keine neuen Zeilen damit einfügen, Sie sollten einen InsertCursor verwenden !
  • Möchten (müssen) Sie diese Einfügungen in einer EditSession vornehmen? Es macht einen großen Unterschied, ob Sie es tun oder nicht. Bei einigen Vorgängen ist dies erforderlich (und es wird langsamer). Wenn dies jedoch nicht erforderlich ist, überspringen Sie die Funktionen zum Rückgängigmachen / Wiederherstellen.
  • Cursor sind teure Ressourcen. Sobald Sie ein Handle zu einem haben, werden Sie garantiert, dass Sie Konsistenz und Isolation haben und das hat Kosten.
  • Zwischenspeichern Sie andere Ressourcen wie Datenbankverbindungen (erstellen und zerstören Sie nicht Ihre Workspace-Referenz) und Tabellenhandles (jedes Mal, wenn Sie eine öffnen oder schließen, müssen mehrere Metadatentabellen gelesen werden).
  • Das Platzieren von FeatureClasses innerhalb oder außerhalb eines FeatureDatasets macht einen großen Unterschied in der Leistung aus. Es ist nicht als organisatorisches Merkmal gedacht!

5.Und zu guter Letzt ...

Verstehen Sie den Unterschied zwischen E / A-gebundenen und CPU-gebundenen Vorgängen

Ich habe ehrlich gesagt darüber nachgedacht, mehr über jedes einzelne dieser Elemente zu erfahren und vielleicht eine Reihe von Blogeinträgen zu erstellen, die sich mit jedem einzelnen dieser Themen befassen, aber die Backlog-Liste meines Kalenders schlug mir nur ins Gesicht und fing an, mich anzuschreien.

Meine zwei Cent.

Ragi Yaser Burhum
quelle
5
Vielen Dank. Ich hätte arbeiten sollen, anstatt diesen Beitrag zu schreiben haha
Ragi Yaser Burhum
3
+1 Vielen Dank für Ihren Beitrag, Herr Burhum. Dies ist die Art von Antwort, die ich erhalten wollte. Wenn ich zweimal abstimmen könnte, könnte ich !! ArcGISScripting (Python) -Benutzer sollten aus dieser Antwort Folgendes entnehmen: Obwohl die Links ArcObjects- und .Net-Konzepte widerspiegeln, sind die zugrunde liegenden COM-Objekte identisch. Wenn Sie diese Objekte verstehen, können Sie Code in einer beliebigen Sprache besser planen. Viele tolle Informationen hier !!
OptimizePrime
1
@OptimizePrime Das ist eine großartige Zusammenfassung. Und Sie haben Recht - Sie können die Auswirkungen von ArcObjects nicht ignorieren, wenn Sie die Leistung von ESRI-Produkten
verringern
1
danke, ich habe store () durch insert cursors ersetzt und in meinen anwendungen viel zeit gespart!
Superrache
5

Im Allgemeinen versuche ich bei Leistungsberechnungen, mich von ESRI-bezogenen Dingen fernzuhalten. Für Ihr Beispiel würde ich vorschlagen, den Prozess in Schritten durchzuführen, den ersten Schritt, in dem die Daten in normale Python-Objekte eingelesen werden, die Berechnungen durchzuführen und den letzten Schritt, in dem in das endgültige räumliche ESRI-Format konvertiert wird. Bei ca. 10.000 Datensätzen könnten Sie wahrscheinlich alles für die Verarbeitung im Speicher ablegen, was einen deutlichen Leistungsgewinn zur Folge hätte.

Anthony -GISCOE-
quelle
Danke für Ihre Antwort. Es ist ein guter Vorschlag. Ich habe begonnen, den Code zu überarbeiten, um die erforderlichen Prozeduren auszuführen, bevor ich arcgisscripting verwende. Nachdem ich seit ArcInfo-Tagen mit der Software gearbeitet habe, finde ich es frustrierend, dass die CPU-Leistung und die Hardwarefähigkeit zunehmen. Die Leistung von ArcGIS Map / Info / Editor XX stagniert. Vielleicht hilft die Einführung von GPUs. Obwohl ein guter Refactor der ESRI-Codebasis auch helfen könnte
OptimizePrime
1

Abhängig von Ihrer Hardware können Sie auch die im ESRI Geocoder-Beispiel angezeigte Option in Betracht ziehen. Es gibt Ihnen ein Framework, mit dem Sie einen großen Datenbestand auflösen und mehrere Instanzen von Python ausführen können, um einen nahezu multithreadbasierten Ansatz zu erhalten. Die Geocodierungsleistung stieg von 180.000 pro Stunde in einer einzelnen Python-Instanz auf über eine Million, da 8 parallele Prozesse auf meinem Computer gestartet wurden.

Ich habe gesehen, dass es zu erheblichen Leistungssteigerungen führt, wenn ich so weit wie möglich davongekommen bin und die Daten in der Datenbank sowie die funktionale Arbeit in meinen Tabellen erhalten und nur das explizite GIS im ESRI-Bereich verwendet wird.

DEWright
quelle
Das sind tolle Ideen. Ich habe die Möglichkeit, einige Prozesse in dieses Skript einzufügen, aber ich stelle fest, dass meine Engpässe die COM-Bibliotheken und die Geodatabase-E / A initialisieren. In Bezug auf E / A habe ich die Notwendigkeit auf ein einziges Schreiben reduziert. Wenn ich mehr Zeit mit der Optimierung verbringe, wird mein Chef einen Anfall bekommen;) Also lasse ich das Threading als letzten Druck der Leistung, wenn er nach mehr verlangt. Im Moment bearbeite ich 60.000 Features pro Minute.
OptimizePrime
0

Diese anderen Forenbeiträge sind möglicherweise interessant, da sie sich im Optimierungskontext befinden, jedoch nicht für Rasterdaten und insgesamt:

Kompilieren von Python-Skripten mit ArcGIS-Geoverarbeitungswerkzeugen?

Verarbeitungszeit mit ArcGIS Hydrology-Toolbox-Tools in eigenständigem Python-Skript im Vergleich zu ArcCatalog?

Die Einstellung "gp.scratchworkspace" hat für mich einen großen Unterschied in einigen Python-Codes bewirkt, die ich für die Abgrenzung von Wasserscheiden geschrieben habe.

Könnten Sie einige Codebeispiele veröffentlichen, die die Nummern 1 und 2 in Ihrem UPDATE zu Ihrer ursprünglichen Frage veranschaulichen? Mich würde interessieren, wie das funktioniert (obwohl ich davon ausgehe, dass Sie es hier nur mit Feature-Class-Daten zu tun haben).

Danke, Tom

türkischgold
quelle