Erros de multiprocessamento - implementação do ArcGIS

13

Fiquei me perguntando se alguém da comunidade aqui tentou usar o multiprocessamento para análises espaciais. Ou seja, estou tentando iterar através de uma série de rasters, criar um trabalho de multiprocessamento para cada um e executá-los através de várias etapas de geoprocessamento dentro de uma função def. Algo ao longo das linhas 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)))    

Agora, o multiprocessamento é executado, geralmente para o primeiro lote! No entanto, continuo com vários erros diferentes ao tentar vários conjuntos de dados (mais de 4 arquivos - ou seja, 4 multiprocessamentos principais), incluindo:

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

e

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

Observe no primeiro erro a pasta estranha criada (no local OutFolderDir) associada às estatísticas focais que quase cria uma réplica exata da saída final.

Minha pergunta é baseada na sua experiência: é impossível criar várias etapas de geoprocessamento em uma função de multiprocessamento? Ou preciso integrar essas etapas em suas etapas individuais de geoprocessamento?

ATUALIZAR

Ainda encontrando erros semelhantes - mover as funções de importação para a função def mostrou que

import arcpy 
from arcpy.sa import *

Não é possível criar uma saída com uma sintaxe adicionada, avisando que import * não é permitido.

ATUALIZAÇÃO # 2

Sei que esta é uma resposta tardia, mas achei que poderia beneficiar alguém para referência futura à minha solução alternativa que permite que o multiprocessamento funcione com o arcpy. O principal problema que encontrei após retornar a esse problema não é a competição dos módulos arcpy, mas a competição pelo scratchWorkspace que o ArcObjects utiliza para salvar os arquivos temporários. Portanto, considere executar um contador no argumento de análise de multiprocessamento para criar um espaço de trabalho exclusivo para cada processo, ou seja

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

Em seguida, na função principal, crie um diretório temporário específico e atribua um espaço de trabalho exclusivo a cada tarefa de multiprocessamento.

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

Espero que ajude e agradeça a Ragi pela sugestão inicial de usar espaços de trabalho temporários separados - ainda desconcertados com o motivo pelo qual originalmente não funcionou.

Recursos adicionais

Blog de multiprocessamento da ESRI

Blog sobre Python, Gis e outras coisas

BJEBN
fonte
Essa sugestão é tão grosseira que não quero formalizá-la em uma resposta, mas você já pensou em executar o ArcGIS em várias máquinas virtuais simultaneamente? (Você pode precisar de uma instalação separada em cada VM, cada uma com sua própria estrutura de diretórios.) Outro pensamento radical é extrair parte do processamento: por exemplo, as estatísticas focais podem ser executadas R. Essas não são boas sugestões para o trabalho de uso geral, porque podem ser mais problemas do que valem, mas quando você pode economizar horas de cada vez, repetidamente, o esforço pode valer a pena.
whuber

Respostas:

7

Cada conexão do IWorkspace (ou seja, cada conexão de banco de dados) possui afinidade de encadeamento. Dois segmentos não podem compartilhar o mesmo espaço de trabalho. Você pode ter um thread como proprietário do recurso e sincronizar o acesso, mas se você estiver usando funções gp diretas, isso ainda não é uma opção.

A maneira mais fácil (coxa) é criar processos separados e, em seguida, sincronizar vários processos (em oposição à sincronização multithread). Mesmo assim, você deve estar ciente do tipo de espaço de trabalho subjacente. se você não estiver usando o arcsde (uma fonte de dados multiusuário), provavelmente usará uma única fonte de dados do usuário (como personal ou filegdb). Lembre-se de que apenas um processo pode escrever por vez! A sincronização (lame) típica para esses cenários é que cada processo paralelo grava em um espaço de trabalho temporário diferente e, em seguida, você mescla tudo no espaço de trabalho de destino em um único processo.

Ragi Yaser Burhum
fonte
Boas sugestões ... Na verdade, embora eu não o tenha adicionado a esta postagem, estou criando uma nova pasta com base no nome da imagem raster e definindo a área de trabalho de cada processo para esse diretório específico. Esses são diretórios de arquivos separados para cada imagem raster e não bancos de dados geográficos separados (eu preciso disso?). Eu tinha planejado usar uma função simples os.walk para encontrar todos os arquivos necessários para movê-los para o meu banco de dados geográfico desejado.
BJEBN
Você está apenas fazendo operações de varredura? Existem threads ou processos de leitura / gravação no mesmo banco de dados geográfico ao mesmo tempo?
Ragi Yaser Burhum
Oi, desculpe, talvez eu tenha ficado um pouco confuso com a declaração anterior. Somente operações de varredura (reprojetar, estatísticas focais, reclassificar etc ...) e todas essas etapas de geoprocessamento são realizadas em uma ordem sequencial (ou precisa ser) para cada imagem de varredura. Essas imagens rasterizadas são salvas em um espaço de trabalho de pasta exclusivo. Todas as rasters originais estão lendo no mesmo diretório (embora não seja a mesma imagem) que cria os trabalhos individuais a serem enviados.
BJEBN
Depois de repensar um pouco, tentei especificar um espaço de trabalho de rascunho específico para cada imagem. O DEM está sendo projetado corretamente, no entanto, isso produziu um novo erro no estágio focalstats - "o tipo <Raster> não é suportado". Eu tentei especificar todo o endereço do diretório, mas sem sorte. Carreguei os rasters projetados no arcgis sem nenhum problema.
BJEBN
Bem, isso significa que você está seguindo em frente. Para as estatísticas focais, depende de como é implementada internamente. Se for uma nova implementação, pode demorar um espaço de trabalho temporário (ou seja, um Geodatabase). No entanto, se for uma daquelas funções que ainda não foram atualizadas (!?!?!), A área de trabalho permitida poderá ser apenas uma pasta. Para essa função GP específica, especifique apenas uma pasta (mantenha o espaço de trabalho de rascunho para o resto) e veja o que acontece.
Ragi Yaser Burhum
5

Você tem vários threads competindo pelo mesmo recurso.

Tente mover sua instrução 'import arcpy' para o destino do multiprocessamento. Você garantirá que o arcpy esteja trabalhando com seu próprio conjunto de variáveis ​​de ambiente e memória.

Parece absurdo, mas mesmo que você esteja configurando variáveis ​​de ambiente no método de destino Multiprocessos, o python ainda está usando um espaço de memória compartilhada para gerenciar o módulo arcpy e, portanto, quaisquer variáveis ​​que você definir.

O Arcpy não é seguro para threads. Ele sempre foi projetado para ser usado em um único processo. Mas existem soluções alternativas.


Minha sugestão foi importar o arcpy dentro do destino para um novo processo.

def _multiprocessing_target(args):
    import arcpy
    ...code
OptimizePrime
fonte
Olá, obrigado pelo seu conselho ... embora pareço ainda ter problemas. Quando você se refere a 'importar arcpy para o destino do multiprocessamento', implica na instrução if__name ... ou na função def. Como eu pensei que importar na função def era inválido.
BJEBN