Errores de multiprocesamiento: implementación de ArcGIS

13

Me preguntaba si alguien más en la comunidad aquí ha intentado usar multiprocesamiento para análisis espaciales. Es decir, estoy tratando de iterar a través de una serie de rásteres, crear un trabajo de multiprocesamiento para cada uno y ejecutarlos a través de una serie de pasos de geoprocesamiento dentro de una función de definición. Algo en la línea 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)))    

¡Ahora se ejecuta el multiprocesamiento, generalmente para el primer lote! Sin embargo, sigo encontrando varios errores diferentes cuando intento varios conjuntos de datos (más de 4 archivos, es decir, multiprocesamiento de 4 núcleos) que incluyen:

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

y

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

Observe en el primer error la carpeta extraña que se crea (en la ubicación OutFolderDir) asociada con las estadísticas focales que casi crean una réplica exacta de la salida final.

Mi pregunta se basa en su experiencia: ¿es imposible crear geoprocesamiento en varios pasos dentro de una función de multiprocesamiento? ¿O necesito agrupar estos pasos en sus pasos de geoprocesamiento individuales?

ACTUALIZAR

Todavía alentando errores similares: mover las funciones de importación a la función def ha demostrado que

import arcpy 
from arcpy.sa import *

no se puede crear una salida con una advertencia de sintaxis agregada que no se permite la importación *.

ACTUALIZACIÓN # 2

Sé que esta es una respuesta tardía, pero pensé que podría beneficiar a alguien más para futuras referencias a mi solución alternativa que permite que el multiprocesamiento funcione con arcpy. El principal problema que encontré después de volver a este problema no es la competencia de los módulos arcpy, sino más bien la competencia sobre el scratchWorkspace que los ArcObjects utilizan para guardar los archivos temporales. Por lo tanto, considere ejecutar un contador en el argumento de análisis de multiprocesamiento para crear un scratchWorkspace único para cada proceso, es decir

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

Luego, en la función principal, haga un directorio temporal específico y asigne un scratchWorkspace único a cada tarea de multiprocesamiento.

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

Espero que eso ayude y gracias a Ragi por la sugerencia inicial de usar espacios de trabajo temporales separados, todavía desconcertado por qué originalmente no funcionó.

Recursos adicionales

Blog de multiprocesamiento de ESRI

Blog de Python, Gis y cosas

BJEBN
fuente
Esta sugerencia es tan cruda que no quiero formalizarla en una respuesta, pero ¿ha considerado ejecutar ArcGIS en varias máquinas virtuales simultáneamente? (Es posible que necesite una instalación por separado en cada VM, cada una con su propia estructura de directorio). Otra idea radical es agotar algunos de los procesos: por ejemplo, se podrían realizar focos estadísticos R. Estas no son buenas sugerencias para el trabajo de propósito general, porque pueden ser más problemáticas de lo que valen, pero cuando puede ahorrar horas a la vez, repetidamente, el esfuerzo podría dar sus frutos.
whuber

Respuestas:

7

Cada conexión de IWorkspace (es decir, cada conexión de base de datos) tiene afinidad de hilos. Dos hilos no pueden compartir el mismo espacio de trabajo. Puede tener un subproceso propio del recurso y luego sincronizar el acceso, pero si va a usar funciones gp directas, entonces esa ni siquiera es una opción.

La forma más fácil (poco convincente) es crear procesos separados y luego realizar una sincronización multiproceso (en oposición a la sincronización multiproceso). Incluso entonces, debe tener en cuenta el tipo de espacio de trabajo subyacente. si no está utilizando arcsde (una fuente de datos multiusuario) probablemente usará una fuente de datos de un solo usuario (como personal o filegdb). ¡Entonces recuerde que eso significa que solo un proceso puede escribir a la vez! La sincronización típica (poco convincente) para estos escenarios es que cada proceso paralelo escribe en un espacio de trabajo temporal diferente y luego lo combina todo en su espacio de trabajo de destino en un solo proceso.

Ragi Yaser Burhum
fuente
Buenas sugerencias ... En realidad, aunque no lo he agregado a esta publicación, estoy creando una nueva carpeta basada en el nombre de la imagen ráster y estableciendo el espacio de trabajo para cada proceso en ese directorio específico. Estos son directorios de archivos separados para cada imagen ráster y no geodatabases separadas (¿lo necesito?). Luego había planeado usar una función simple os.walk para encontrar todos esos archivos que necesitaba moverlos a mi geodatabase de archivos deseada.
BJEBN
¿Solo estás haciendo operaciones de trama? ¿Hay hilos o procesos que leen / escriben en la misma geodatabase al mismo tiempo?
Ragi Yaser Burhum
Hola, lo siento, podría haber sido un poco confuso con la declaración anterior. Solo las operaciones de trama (reproyección, estadísticas centrales, reclasificación, etc.) y todos esos pasos de geoprocesamiento se realizan en un orden secuencial (o deben realizarse) para cada imagen de trama. Estas imágenes ráster se guardan en un espacio de trabajo de carpeta único. Todos los rásteres originales están leyendo desde el mismo directorio (aunque no la misma imagen) ya que eso crea los trabajos individuales que se enviarán.
BJEBN
Después de repensar un poco, traté de especificar un espacio de trabajo scratch específico para cada imagen. El DEM se está proyectando correctamente, sin embargo, esto ha producido un nuevo error en la etapa de estadísticas centrales: "el tipo <Raster> no es compatible". Intenté especificar la dirección completa del directorio pero sin suerte. He cargado los rásteres proyectados en arcgis sin ningún problema.
BJEBN
Bueno, eso significa que estás avanzando. Para los centros de coordinación, depende de cómo se implemente internamente. Si se trata de una nueva implementación, puede ocupar un espacio de trabajo temporal (es decir, una Geodatabase). Sin embargo, si es una de esas funciones que aún no se ha actualizado (!?!?!), El espacio de trabajo que permite puede ser solo una carpeta. Para esa función GP en particular, especifique solo una carpeta (mantenga el espacio de scratchworks para el resto) y vea qué sucede.
Ragi Yaser Burhum
5

Tienes varios hilos que compiten por el mismo recurso.

Intente mover su declaración 'import arcpy' al objetivo del multiprocesamiento. Se asegurará de que arcpy esté trabajando con su propio conjunto de variables de entorno y memoria.

Suena absurdo, pero a pesar de que está configurando variables de entorno en el método de destino Multiproceso, python todavía está utilizando un espacio de memoria compartida para administrar el módulo arcpy y, por lo tanto, cualquier variable que establezca.

Arcpy no es seguro para subprocesos. Siempre tuvo la intención de ser utilizado dentro de un solo proceso. Pero hay soluciones alternativas.


Mi sugerencia fue importar arcpy dentro del objetivo para un nuevo proceso.

def _multiprocessing_target(args):
    import arcpy
    ...code
OptimizePrime
fuente
Hola, gracias por tu consejo ... aunque parece que todavía tengo problemas. Cuando se refiere a 'importar arcpy en el objetivo del multiprocesamiento', ¿se refiere a la declaración if__name ... o dentro de la función def. Como pensé, importar en la función def no era válido.
BJEBN