Błędy wieloprocesowe - implementacja ArcGIS

13

Zastanawiałem się, czy ktoś w tej społeczności próbował użyć przetwarzania wieloprocesorowego do analiz przestrzennych. Mianowicie próbuję iterować przez serię rastrów, utworzyć dla każdego zadanie wieloprocesowe i przeprowadzić je przez szereg etapów geoprzetwarzania w ramach jednej funkcji def. Coś w stylu

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)))    

Teraz działa wiele procesów, zwykle dla pierwszej partii! Jednak ciągle napotykam kilka różnych błędów podczas próby kilku zestawów danych (więcej niż 4 pliki - tj. Czterordzeniowy proces wieloprocesowy), w tym:

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).

i

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

Zauważ w pierwszym błędzie dziwny folder, który jest tworzony (w lokalizacji OutFolderDir) powiązany ze statystykami ogniskowymi, które prawie tworzą dokładną replikę końcowego wyniku.

Moje pytanie opiera się na twoim doświadczeniu. Czy niemożliwe jest utworzenie kilkuetapowego geoprzetwarzania w ramach jednej funkcji wieloprocesowej? Czy też muszę ułożyć te kroki w osobne etapy geoprzetwarzania?

AKTUALIZACJA

Wciąż szyfruję podobne błędy - pokazało to przeniesienie funkcji importowania do funkcji def

import arcpy 
from arcpy.sa import *

nie można utworzyć wyniku z dodanym ostrzeżeniem o składni, że import * jest niedozwolony.

AKTUALIZACJA # 2

Wiem, że to późna odpowiedź, ale pomyślałem, że może to przydać się komuś innemu w przyszłości w odniesieniu do mojego obejścia, które pozwala na wieloprzetwarzanie do pracy z arcpy. Głównym problemem, który znalazłem po powrocie do tego problemu, nie jest rywalizacja modułów arcpy, ale raczej rywalizacja o scratchWorkspace, który ArcObjects wykorzystuje do zapisywania plików tymczasowych. Dlatego rozważ uruchomienie licznika w argumencie przetwarzania wieloprocesowego, aby utworzyć unikalny obszar roboczy scratch dla każdego procesu, tj

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

Następnie w głównej funkcji utwórz konkretny katalog tymczasowy i przypisz unikalny scratchWorkspace do każdego zadania wieloprocesowego.

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

Mam nadzieję, że to pomaga i dziękuje Ragi za początkową sugestię korzystania z oddzielnych przestrzeni roboczych w temp. - nadal jest zaskoczony, dlaczego pierwotnie nie działał.

Dodatkowe zasoby

Blog wieloprocesowy ESRI

Blog Python, Gis i Stuff

BJEBN
źródło
Ta sugestia jest tak prymitywna, że ​​nie chcę sformalizować jej w odpowiedzi, ale czy rozważałeś jednoczesne uruchomienie ArcGIS na wielu maszynach wirtualnych? (Może być potrzebna osobna instalacja na każdej maszynie wirtualnej, każda z własną strukturą katalogów.) Inną radykalną myślą jest wyodrębnienie części przetwarzania: na przykład można ustawić stacje ogniskowe R. Nie są to dobre sugestie do prac ogólnych, ponieważ mogą być bardziej kłopotliwe niż warte, ale gdy możesz zaoszczędzić wiele godzin, wysiłek może się opłacić.
whuber

Odpowiedzi:

7

Każde połączenie IWorkspace (tj. Każde połączenie z bazą danych) ma powinowactwo do wątków. Dwa wątki nie mogą współdzielić tego samego obszaru roboczego. Możesz mieć jeden wątek będący właścicielem zasobu, a następnie zsynchronizować dostęp, ale jeśli zamierzasz używać prostych funkcji GP, nie jest to nawet możliwe.

Najłatwiejszym (lame) sposobem jest utworzenie osobnych procesów, a następnie synchronizacja wieloprocesowa (w przeciwieństwie do synchronizacji wielowątkowej). Nawet wtedy powinieneś być świadomy podstawowego typu obszaru roboczego. jeśli nie korzystasz z arcsde (źródło danych dla wielu użytkowników), prawdopodobnie użyjesz źródła danych dla jednego użytkownika (takiego jak personal lub filegdb). Pamiętaj, że oznacza to, że tylko jeden proces może pisać jednocześnie! Typowa (słaba) synchronizacja dla tych scenariuszy polega na tym, że każdy równoległy proces zapisuje w innym tymczasowym obszarze roboczym, a następnie łączy się wszystko z docelowym obszarem roboczym w jednym procesie.

Ragi Yaser Burhum
źródło
Dobre sugestie ... W rzeczywistości, chociaż nie dodałem go do tego postu, tworzę nowy folder na podstawie nazwy obrazu rastrowego i ustawiam obszar roboczy dla każdego procesu na ten konkretny katalog. Są to osobne katalogi plików dla każdego obrazu rastrowego, a nie oddzielne geobazy (czy potrzebuję tego?). Następnie planowałem użyć prostej funkcji os.walk, aby znaleźć wszystkie potrzebne pliki, przenieść je do żądanej geobazy danych.
BJEBN,
Czy robisz tylko operacje rastrowe? Czy są jakieś wątki lub procesy, które jednocześnie odczytują / zapisują tę samą geobazę?
Ragi Yaser Burhum,
Cześć, przepraszam, mogłem być nieco niejasny w stosunku do poprzedniego oświadczenia. Tylko operacje rastrowe (reprojekt, stacje ogniskowe, przeklasyfikowanie itp.) I wszystkie te kroki geoprzetwarzania są wykonywane w kolejności sekwencyjnej (lub muszą być) dla każdego obrazu rastrowego. Te obrazy rastrowe są zapisywane w unikatowym obszarze roboczym folderów. Wszystkie oryginalne rastry odczytują z tego samego katalogu (choć nie tego samego obrazu), ponieważ tworzy to pojedyncze zadania do wysłania.
BJEBN,
Po pewnym przemyśleniu próbowałem również określić konkretny obszar roboczy rysowania dla każdego obrazu. DEM jest poprawnie wyświetlany, jednak spowodowało to nowy błąd na etapie focalstats - „typ <Raster> nie jest obsługiwany”. Próbowałem podać cały adres katalogu, ale bez powodzenia. Bez problemu załadowałem rzutowane rastry do arcgis.
BJEBN,
To oznacza, że ​​idziesz naprzód. W przypadku focalstats zależy to od tego, jak jest implementowany wewnętrznie. Jeśli jest to nowa implementacja, może zająć obszar scratchworkspace (tj. Geobazę). Jeśli jednak jest to jedna z tych funkcji, które nie zostały jeszcze zaktualizowane (!?!?!), Dozwolony obszar roboczy może być tylko folderem. Dla tej konkretnej funkcji GP określ tylko folder (zachowaj przestrzeń scratchwork dla reszty) i zobacz, co się stanie.
Ragi Yaser Burhum,
5

Masz kilka wątków konkurujących o ten sam zasób.

Spróbuj przenieść instrukcję „arcpy importu” na cel procesu wieloprocesowego. Zapewnisz, że arcpy działa z własnym zestawem zmiennych środowiskowych i pamięci.

Brzmi to absurdalnie, ale nawet jeśli ustawiasz zmienne środowiskowe w metodzie docelowej Multiprocess, python nadal używa przestrzeni pamięci współużytkowanej do zarządzania modułem arcpy, a zatem dowolnymi ustawionymi zmiennymi.

Arcpy nie jest bezpieczne dla wątków. Zawsze miał być stosowany w jednym procesie. Ale są obejścia.


Moją sugestią było zaimportowanie arcpy w celu dla nowego procesu.

def _multiprocessing_target(args):
    import arcpy
    ...code
OptimizePrime
źródło
Cześć, dziękuję za twoją radę ... chociaż nadal mam problemy. Kiedy odwołujesz się do „importuj arcpy do celu wieloprocesowego przetwarzania”, sugerujesz, że pod instrukcją if__name ... lub faktycznie w ramach funkcji def. Jak myślałem, importowanie do funkcji def było nieprawidłowe.
BJEBN,