Erreurs de multitraitement - Implémentation d'ArcGIS

13

Je me demandais si quelqu'un d'autre dans la communauté ici avait tenté d'utiliser le multi-traitement pour les analyses spatiales. À savoir, j'essaie de parcourir une série de rasters, de créer un travail de multitraitement pour chacun et de les exécuter à travers un certain nombre d'étapes de géotraitement dans une fonction def. Quelque chose dans le sens de

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

Maintenant, le multitraitement s'exécute, généralement pour le premier lot! Cependant, je continue à rencontrer plusieurs erreurs différentes lors de la tentative de plusieurs ensembles de données (plus de 4 fichiers - c'est-à-dire multiprocessing 4 cœurs), notamment:

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

et

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

Remarquez dans la première erreur l'étrange dossier créé (à l'emplacement OutFolderDir) associé aux statistiques focales qui crée presque une réplique exacte de la sortie finale.

Ma question est basée sur votre expérience, est-il impossible de créer un géotraitement en plusieurs étapes au sein d'une fonction multiprocesseur? Ou dois-je intégrer ces étapes dans leurs étapes de géotraitement individuelles?

MISE À JOUR

Toujours rencontrant des erreurs similaires - le déplacement des fonctions d'importation vers la fonction def a montré que

import arcpy 
from arcpy.sa import *

ne peut pas créer une sortie avec une syntaxe ajoutée avertissant que l'importation * n'est pas autorisée.

MISE À JOUR # 2

Je sais que c'est une réponse tardive, mais j'ai pensé que cela pourrait bénéficier à quelqu'un d'autre pour une référence future à ma solution de contournement qui permet au multitraitement de fonctionner avec arcpy. Le problème principal que j'ai trouvé après être revenu à ce problème n'est pas la concurrence des modules arcpy mais plutôt la concurrence sur le scratchWorkspace que les ArcObjects utilisent pour enregistrer les fichiers temporaires. Par conséquent, envisagez d'exécuter un compteur dans l'argument d'analyse multiprocessing pour créer un scratchWorkspace unique pour chaque processus, c'est-à-dire

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

Ensuite, dans la fonction principale, créez un répertoire temporaire spécifique et affectez un scratchWorkspace unique à chaque tâche de multitraitement.

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

J'espère que cela aide et merci à Ragi pour la suggestion initiale d'utiliser des espaces de travail temporaires séparés - toujours déconcerté par les raisons pour lesquelles cela ne fonctionnait pas à l'origine.

Ressources supplémentaires

Blog ESRI Multiprocessing

Blog Python, Gis et Stuff

BJEBN
la source
Cette suggestion est si grossière que je ne veux pas la formaliser dans une réponse, mais avez-vous envisagé d'exécuter ArcGIS sur plusieurs machines virtuelles simultanément? (Vous pourriez avoir besoin d'une installation distincte dans chaque machine virtuelle, chacune avec sa propre structure de répertoires.) Une autre idée radicale est de réduire une partie du traitement: par exemple, les focales peuvent être effectuées dans R. Ce ne sont pas de bonnes suggestions pour un travail à usage général, car elles peuvent être plus problématiques qu'elles n'en valent, mais lorsque vous pouvez économiser des heures à la fois, à plusieurs reprises, l'effort pourrait être payant.
whuber

Réponses:

7

Chaque connexion IWorkspace (c'est-à-dire chaque connexion à la base de données) a une affinité de thread. Deux threads ne peuvent pas partager le même espace de travail. Vous pouvez avoir un thread propriétaire de la ressource, puis synchroniser l'accès, mais si vous allez utiliser des fonctions gp directes, ce n'est même pas une option.

Le moyen le plus simple (boiteux) consiste à créer des processus séparés, puis à effectuer une synchronisation multi-processus (par opposition à une synchronisation multithread). Même dans ce cas, vous devez connaître le type d'espace de travail sous-jacent. si vous n'utilisez pas arcsde (une source de données multi-utilisateurs), vous utiliserez probablement une seule source de données utilisateur (comme personal ou filegdb). N'oubliez pas que cela signifie qu'un seul processus peut écrire à la fois! La synchronisation typique (boiteuse) pour ces scénarios est que chaque processus parallèle écrit dans un espace de travail temporaire différent et que vous fusionnez tout cela dans votre espace de travail de destination en un seul processus.

Ragi Yaser Burhum
la source
Bonnes suggestions ... En fait, bien que je ne l'aie pas ajouté à ce message, je crée un nouveau dossier basé sur le nom de l'image raster et définit l'espace de travail pour chaque processus dans ce répertoire spécifique. Il s'agit de répertoires de fichiers séparés pour chaque image raster et non de géodatabases distinctes (en ai-je besoin?). J'avais alors prévu d'utiliser une simple fonction os.walk pour trouver tous les fichiers dont j'avais besoin pour les déplacer vers la géodatabase fichier souhaitée.
BJEBN
Faites-vous uniquement des opérations raster? Existe-t-il des threads ou des processus de lecture / écriture dans la même géodatabase en même temps?
Ragi Yaser Burhum,
Salut, désolé, j'aurais peut-être été un peu flou avec la déclaration précédente. Seules les opérations raster (reprojet, focales, reclassification etc ...) et toutes ces étapes de géotraitement sont effectuées dans un ordre séquentiel (ou doivent l'être) pour chaque image raster. Ces images raster sont enregistrées dans un espace de travail de dossier unique. Tous les rasters d'origine lisent à partir du même répertoire (pas la même image cependant) car cela crée les tâches individuelles à envoyer.
BJEBN
Après avoir repensé quelque peu, j'ai essayé de spécifier un espace de travail spécifique pour chaque image. Les DEM sont correctement projetés, mais cela a produit une nouvelle erreur au stade des focales - "le type <Raster> n'est pas pris en charge". J'ai essayé de spécifier l'adresse du répertoire entier mais sans succès. J'ai chargé les rasters projetés dans arcgis sans problème.
BJEBN
Eh bien, cela signifie que vous allez de l'avant. Pour les focales, cela dépend de la façon dont elles sont mises en œuvre en interne. S'il s'agit d'une nouvelle implémentation, elle peut prendre un espace de travail (c'est-à-dire une géodatabase). Cependant, s'il s'agit d'une de ces fonctions qui n'a pas encore été mise à niveau (!?!?!), L'espace de travail qu'il autorise ne peut être qu'un dossier. Pour cette fonction GP particulière, spécifiez uniquement un dossier (conservez l'espace de travail pour le reste) et voyez ce qui se passe.
Ragi Yaser Burhum
5

Vous avez plusieurs threads en compétition pour la même ressource.

Essayez de déplacer votre instruction «import arcpy» dans la cible du multitraitement. Vous vous assurerez qu'arcpy fonctionne avec son propre ensemble de variables d'environnement et de mémoire.

Cela semble absurde, mais même si vous définissez des variables d'environnement dans la méthode cible Multiprocess, python utilise toujours un espace mémoire partagé pour gérer le module arcpy et donc toutes les variables que vous définissez.

Arcpy n'est pas sûr pour les threads. Il a toujours été conçu pour être utilisé dans un seul processus. Mais il existe des solutions de contournement.


Ma suggestion était d'importer arcpy dans la cible pour un nouveau processus.

def _multiprocessing_target(args):
    import arcpy
    ...code
OptimizePrime
la source
Salut, merci pour vos conseils ... même si je semble avoir encore des problèmes. Lorsque vous faites référence à «importer arcpy dans la cible du multitraitement», vous impliquez-vous sous l'instruction if__name ... ou réellement dans la fonction def. Comme je pensais que l'importation dans la fonction def n'était pas valide.
BJEBN