Multiprocessing Errors - ArcGIS-Implementierung

13

Ich habe mich gefragt, ob irgendjemand in der Community hier versucht hat, Multi-Processing für räumliche Analysen zu verwenden. Ich versuche nämlich, eine Reihe von Rastern zu durchlaufen, für jeden einen Multiprocessing-Job zu erstellen und sie durch eine Reihe von Geoverarbeitungsschritten innerhalb einer Def-Funktion zu führen. Etwas in der Art von

def net(RasterImage, OutFolderDir):
    arcpy.env.overwriteOutput = True  
    arcpy.env.workspace = OutFolderDir 
    DEM_Prj = DEM_Prj.tif

    try:
        arcpy.ProjectRaster_management(RasterImage, DEM_Prj....
        FocalStatistics(DEM_prj....)
        ...

if __name__ == '__main__':  
    InputFolder = r'C:\test\somepath'  
    Output = r'C:\test\somepath2'  
    arcpy.env.workspace = InputFolder  
    arcpy.env.scratchWorkspace = r'C:\test.gdb'    

    fcs = arcpy.ListRasters('*')
    pool = multiprocessing.Pool(4)   
    jobs = []                 
    for fc in fcs:
        rIn = os.path.join(InputFolder,fc)
        rOut = os.path.join(Output,fc[:-4])
        jobs.append(pool.apply_async(net,(rIn, rOut)))    

Jetzt läuft die Mehrfachverarbeitung, normalerweise für die erste Charge! Beim Versuch, mehrere Datensätze (mehr als 4 Dateien - dh 4 Kern-Multiprozessoren) zu verarbeiten, treten jedoch immer wieder verschiedene Fehler auf, darunter:

ERROR 010302: Unable to create the output raster: C:\somepath\sr6f8~1\FocalSt_srtm1
ERROR 010067: Error in executing grid expression.
Failed to execute (FocalStatistics).

und

ERROR 999999: Error executing function.
Failed to copy raster dataset
Failed to execute (ProjectRaster)

Beachten Sie im ersten Fehler den seltsamen Ordner, der erstellt wird (am Speicherort von OutFolderDir) und der Fokusstatistik zugeordnet ist, die nahezu eine exakte Kopie der endgültigen Ausgabe erstellt.

Meine Frage basiert auf Ihren Erfahrungen. Ist es unmöglich, mehrere Geoverarbeitungsschritte in einer Multiprocessing-Funktion zu erstellen? Oder muss ich diese Schritte in ihre einzelnen Geoverarbeitungsschritte unterteilen?

AKTUALISIEREN

Immer noch ähnliche Fehler aufgetreten - das Verschieben der Importfunktionen in die def-Funktion hat dies gezeigt

import arcpy 
from arcpy.sa import *

Es kann keine Ausgabe mit einer hinzugefügten Syntax-Warnung erstellt werden, dass der Import * nicht zulässig ist.

UPDATE # 2

Ich weiß, dass dies eine verspätete Antwort ist, aber ich dachte, es könnte jemand anderem zugute kommen, wenn ich in Zukunft auf meine Problemumgehung zurückgreifen möchte, die es ermöglicht, dass Multiprocessing mit Arcpy funktioniert. Das Hauptproblem, das ich nach der Rückkehr zu diesem Problem festgestellt habe, ist nicht die Konkurrenz der arcpy-Module, sondern die Konkurrenz um den scratchWorkspace, den ArcObjects zum Speichern der temporären Dateien verwendet. Ziehen Sie daher in Betracht, einen Zähler für das Multiprocessing-Parsing-Argument auszuführen, um einen eindeutigen scratchWorkspace für jeden Prozess zu erstellen, d. H

Counter = 0 
for fc in fcs:              
    rIn = os.path.join(InputFolder,fc)              
    rOut = os.path.join(Output,fc[:-4])                    
    jobs.append(pool.apply_async(net,(rIn, rOut,Counter)))            
    Counter += 1

Erstellen Sie dann in der Hauptfunktion ein bestimmtes temporäres Verzeichnis und weisen Sie jeder Multiprozessor-Aufgabe einen eindeutigen scratchWorkspace zu.

def main(RasterImage,OutFolderDir,Counter)      
    TempFolder = os.path.join(os.path.dirname(OutFolderDir),'Temp_%s'%  (Counter))      
    os.mkdir(TempFolder)      
    arcpy.scratchWorkspace = TempFolder      
    ... 

Hoffe das hilft und danke an Ragi für den anfänglichen Vorschlag, separate temporäre Arbeitsbereiche zu verwenden - immer noch ratlos, warum es ursprünglich nicht funktioniert hat.

Zusätzliche Ressourcen

ESRI Multiprocessing Blog

Python, Gis und Stuff Blog

BJEBN
quelle
Dieser Vorschlag ist so grob, dass ich ihn nicht in einer Antwort formalisieren möchte. Haben Sie jedoch darüber nachgedacht, ArcGIS auf mehreren virtuellen Maschinen gleichzeitig auszuführen? (Möglicherweise benötigen Sie eine separate Installation in jeder VM mit jeweils einer eigenen Verzeichnisstruktur.) Ein weiterer radikaler Gedanke ist, einen Teil der Verarbeitung auszulagern: Beispielsweise könnten in focalstats ausgeführt werden R. Dies sind keine guten Vorschläge für allgemeine Arbeiten, da sie mehr Mühe bereiten als sie wert sind. Wenn Sie jedoch mehrmals Stunden auf einmal sparen können, könnte sich der Aufwand lohnen.
whuber

Antworten:

7

Jede IWorkspace-Verbindung (dh jede Datenbankverbindung) hat eine Thread-Affinität. Zwei Threads können nicht denselben Arbeitsbereich gemeinsam nutzen. Sie können die Ressource einem Thread gehören lassen und dann den Zugriff synchronisieren. Wenn Sie jedoch gerade GP-Funktionen verwenden, ist dies sogar keine Option.

Am einfachsten (lahmsten) ist es, separate Prozesse zu erstellen und dann eine Synchronisation mit mehreren Prozessen durchzuführen (im Gegensatz zur Synchronisation mit mehreren Threads). Auch dann sollten Sie den zugrunde liegenden Arbeitsbereichstyp kennen. Wenn Sie nicht arcsde (eine Mehrbenutzer-Datenquelle) verwenden, verwenden Sie wahrscheinlich eine einzelne Benutzer-Datenquelle (wie personal oder filegdb). Dann denken Sie daran, dass immer nur ein Prozess gleichzeitig schreiben kann! Die typische (lahme) Synchronisation für diese Szenarien besteht darin, dass jeder parallele Prozess in einen anderen temporären Arbeitsbereich schreibt und Sie dann alles in Ihrem Zielarbeitsbereich in einem einzigen Prozess zusammenführen.

Ragi Yaser Burhum
quelle
Gute Vorschläge ... Obwohl ich diesen Beitrag noch nicht hinzugefügt habe, erstelle ich einen neuen Ordner basierend auf dem Namen des Rasterbilds und lege den Arbeitsbereich für jeden Prozess auf dieses bestimmte Verzeichnis fest. Hierbei handelt es sich um separate Dateiverzeichnisse für jedes Rasterbild und nicht um separate Geodatabases (benötige ich das?). Ich hatte damals geplant, eine einfache os.walk-Funktion zu verwenden, um alle benötigten Dateien zu finden und in die gewünschte File-Geodatabase zu verschieben.
BJEBN
Führen Sie nur Rasteroperationen durch? Gibt es Threads oder Prozesse, die gleichzeitig in dieselbe Geodatabase lesen / schreiben?
Ragi Yaser Burhum
Hallo, tut mir leid, dass ich mit der vorherigen Aussage vielleicht etwas unklar war. Nur Rasteroperationen (Neuprojektieren, Focalstats, Neuklassifizieren usw.) und alle diese Geoverarbeitungsschritte werden in einer sequenziellen Reihenfolge für jedes Rasterbild ausgeführt (oder müssen dies sein). Diese Rasterbilder werden in einem eindeutigen Ordnerarbeitsbereich gespeichert. Alle Original-Raster lesen aus demselben Verzeichnis (jedoch nicht aus demselben Bild) wie die einzelnen zu sendenden Jobs.
BJEBN
Nachdem ich etwas überlegt hatte, versuchte ich, für jedes Bild auch einen bestimmten Arbeitsbereich anzugeben. Die DEM werden korrekt projiziert, dies hat jedoch zu einem neuen Fehler in der Fokusstatistik geführt - "Typ <Raster> wird nicht unterstützt". Ich habe versucht, die gesamte Verzeichnisadresse anzugeben, aber ohne Glück. Ich habe die projizierten Raster problemlos in arcgis geladen.
BJEBN
Nun, das heißt, Sie bewegen sich vorwärts. Für die Focalstats hängt es davon ab, wie sie intern implementiert werden. Wenn es sich um eine neue Implementierung handelt, kann ein Scratchworkspace (dh eine Geodatabase) verwendet werden. Wenn es sich jedoch um eine dieser Funktionen handelt, die noch nicht aktualisiert wurden (!?!?!), Ist der zulässige Arbeitsbereich möglicherweise nur ein Ordner. Geben Sie für diese bestimmte GP-Funktion nur einen Ordner an (behalten Sie den Arbeitsbereich für den Rest bei) und sehen Sie, was passiert.
Ragi Yaser Burhum
5

Sie haben mehrere Threads, die um dieselbe Ressource konkurrieren.

Versuchen Sie, die Anweisung 'import arcpy' in das Ziel der Mehrfachverarbeitung zu verschieben. Sie stellen sicher, dass arcpy mit einem eigenen Satz von Umgebungsvariablen und Speicher arbeitet.

Es klingt absurd, aber obwohl Sie Umgebungsvariablen in der Multiprocess-Zielmethode festlegen, verwendet Python immer noch einen gemeinsam genutzten Speicherbereich, um das Arcpy-Modul und daher alle von Ihnen festgelegten Variablen zu verwalten.

Arcpy ist nicht threadsicher. Es war immer dafür gedacht, innerhalb eines einzigen Prozesses verwendet zu werden. Es gibt jedoch Problemumgehungen.


Mein Vorschlag war, arcpy innerhalb des Ziels für den neuen Prozess zu importieren.

def _multiprocessing_target(args):
    import arcpy
    ...code
OptimizePrime
quelle
Hallo, danke für deinen Rat ... obwohl ich anscheinend immer noch Probleme habe. Wenn Sie sich auf "arcpy in das Ziel der Mehrfachverarbeitung importieren" beziehen, implizieren Sie dies unter der if__name ... -Anweisung oder tatsächlich innerhalb der def-Funktion. Wie ich dachte, war der Import in die Def-Funktion ungültig.
BJEBN