Desempenho do ArcGISScripting e grandes conjuntos de dados espaciais

38

Atualmente, estou escrevendo um script python usando o módulo arcgisscripting para processar um conjunto de dados razoavelmente grande (~ 10.000 registros no total) normalizado em um pequeno número de tabelas, 8 no total. O processo consiste em criar um recurso baseado em tuplas de coordenadas (x, y) e criar um gráfico (nós e linhas) usando os relacionamentos nas outras 7 tabelas para orientação. A saída final é um geodatabase pessoal (pgdb / fgdb) com nós e conjuntos de dados espaciais de bordas que representam visualmente os relacionamentos.

Minha tentativa inicial foi usar consultas das novas tabelas de geodatabase e conjuntos de registros SearchCursor para preencher tabelas de links (InsertCursor) para os relacionamentos muitos-para-muitos que ocorrem. Isso funcionou muito bem, exceto pelo tempo de processamento de 15 a 20 minutos.

Usando o módulo cProfiler no Python, ficou claro que 'debulhar' um geodatabase pessoal ao executar as consultas de pesquisa para preencher as tabelas de links com solicitações de cursores (cursores de Pesquisa e Inserção) causou um desempenho terrível.

Com um pouco de refatoração, consegui obter o tempo de processamento abaixo de 2,5 minutos. O trade-off foi a construção parcial do esquema de geodatabase no código e a limitação das solicitações de cursores de script de arco para InsertCursors depois que todos os relacionamentos foram reunidos.

Minha pergunta é sobre desempenho;

  • Quais técnicas as pessoas usaram para manter tempos de computação razoáveis ​​ao trabalhar com um grande conjunto de dados?
  • Há algum método recomendado pela ESRI que eu perdi na minha busca por otimização?

    Entendo a sobrecarga incorrida ao criar um cursor de arcgisscripting, principalmente se for de um geodatabase pessoal, embora após uma longa pesquisa por respostas relacionadas a desempenho deste site e do Google tenha a impressão de que o desempenho não está na vanguarda dos empreendimentos das pessoas .

  • Como usuário de produtos ESRI, espera-se e tolera essas defasagens de desempenho?

ATUALIZAR

Após algum trabalho com este produto, acumulei uma lista de técnicas de otimização que adotaram um processo de conversão de informações espaciais de um formato de propriedade para um geodatabase. Isso foi desenvolvido para o geodatabase pessoal e de arquivos. Petiscos:

  1. Leia seus dados e racionalize-os na memória. Isso reduzirá seu tempo pela metade.

  2. Crie classes de recurso e tabelas na memória. Use o conjunto de dados do recurso keywork 'in_memory' para usar sua memória como disco ram, executar suas funções lá e depois gravar no disco

  3. Para gravar no disco, use a CopyFeatureclass para classes de recursos e CopyRow para tabelas.

Essas três coisas levaram um script que converteu mais de 100.000 recursos em um geodatabase de 30 minutos a 30 - 40 segundos, incluindo classes de relacionamento. Eles não devem ser usados ​​de ânimo leve, a maioria dos métodos acima usa muita memória, o que pode causar problemas se você não estiver prestando atenção.

OptimizePrime
fonte
1
Você já tentou usar um formato de armazenamento diferente? Como um geodatabase de arquivo é executado?
Drek Swingley
Um geodatabase de arquivo tem desempenho ligeiramente pior que um geodatabase pessoal. Passei ontem configurando e ajustando uma instância do ArcSDE para testar o desempenho em um formato corporativo. Eu vou mantê-lo informado sobre as minhas conclusões
OptimizePrime
2
Isso não ajuda você agora, mas na versão 10.1, o desempenho do cursor no Python foi aprimorado por um grande fator (algo na ordem da magnitude em casos médios) com o novo módulo de acesso a dados.
Jason Scheirer
In_memory usa o InMemoryWorkspace edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriDataSourcesGDB/… que, após um número arbitrário de linhas, despeja tudo em um ScratchWorkspaceFactory (ou seja, FileGDB) e depende do FileGDB para fazer todo o trabalho
Ragi Yaser Burhum

Respostas:

56

Embora essa pergunta já tenha sido respondida, pensei em dar um toque de dois centavos.

AVISO LEGAL : Eu trabalhei para a ESRI na equipe do GeoDatabase por alguns anos e fiquei encarregado de manter várias partes do código do GeoDatabase (controle de versão, cursores, edições de edição, histórico, classes de relacionamento etc.).

Eu acho que a maior fonte de problemas de desempenho com o código ESRI não é entender as implicações do uso de objetos diferentes, particularmente os "pequenos" detalhes das várias abstrações do GeoDatabase! Com muita frequência, a conversa muda para o idioma usado como culpado dos problemas de desempenho. Em alguns casos, pode ser. Mas não o tempo todo. Vamos começar com a discussão do idioma e voltar ao trabalho.

1.- A linguagem de programação que você escolhe só importa quando você está fazendo algo que é complicado, em um loop apertado. Na maioria das vezes, esse não é o caso.

O grande elefante na sala é que, no centro de todo o código ESRI, você tem ArcObjects - e o ArcObjects é escrito em C ++ usando COM . Há um custo para se comunicar com esse código. Isso é verdade para C #, VB.NET, python ou qualquer outra coisa que você esteja usando.

Você paga um preço na inicialização desse código. Isso pode ser um custo insignificante se você fizer isso apenas uma vez.

Você paga um preço por cada tempo subsequente em que interagir com o ArcObjects.

Pessoalmente, costumo escrever código para meus clientes em C #, porque é fácil e rápido o suficiente. No entanto, toda vez que eu quero mover dados ou fazer algum processamento para grandes quantidades de dados já implementadas no Geoprocessamento, eu apenas inicializo o subsistema de script e passo meus parâmetros. Por quê?

  • Já está implementado. Então, por que reinventar a roda?
  • Na verdade, pode ser mais rápido . "Mais rápido do que escrever em C #?" Sim! Se eu implemente, digamos, o carregamento manual de dados, significa que pago o preço da alternância de contexto .NET em um loop restrito. Todo GetValue, Insert, ShapeCopy tem um custo. Se eu fizer uma chamada no GP, todo o processo de carregamento de dados ocorrerá na implementação real do GP - em C ++ no ambiente COM. Não pago o preço pela alternância de contexto porque não há - e, portanto, é mais rápido.

Ah, sim, então a solução é usar muitas funções de geoprocessamento. Na verdade, você tem que ter cuidado.

2. GP é uma caixa preta que copia dados (potencialmente desnecessariamente) em torno de

É uma espada de dois gumes. É uma caixa preta que faz mágica internamente e cospe resultados - mas esses resultados costumam ser duplicados. 100.000 linhas podem ser facilmente convertidas em 1.000.000 de linhas no disco após a execução dos dados em 9 funções diferentes. Usar apenas funções GP é como criar um modelo linear GP, e bem ...

3. Encadear muitas funções GP para grandes conjuntos de dados é altamente ineficiente. Um modelo de GP é (potencialmente) equivalente a executar uma consulta de uma maneira realmente muito muito burra

Agora não me interpretem mal. Eu amo os GP Models - isso me impede de escrever código o tempo todo. Mas também estou ciente de que não é a maneira mais eficiente de processar grandes conjuntos de dados.

Você já ouviu falar de um planejador de consultas ? Seu trabalho é examinar a instrução SQL que você deseja executar, gerar um plano de execução na forma de um gráfico direcionado que se parece muito com um Modelo GP , examinar as estatísticas armazenadas no banco de dados e escolher a opção mais adequada. ordem ideal para executá-los . O GP apenas os executa na ordem em que você coloca as coisas, porque não possui estatísticas para fazer algo de maneira mais inteligente - você é o planejador de consultas . E adivinha? A ordem em que você executa as coisas depende muito do seu conjunto de dados. A ordem em que você executa as coisas pode fazer a diferença entre dias e segundos e cabe a você decidir.

"Ótimo" você diz, eu não vou escrever as coisas sozinho e ter cuidado com a forma como escrevo as coisas. Mas você entende abstrações do GeoDatabase?

4.Não entender as abstrações do GeoDatabase podem mordê-lo facilmente

Em vez de apontar tudo o que pode causar um problema, deixe-me apontar alguns erros comuns que vejo o tempo todo e algumas recomendações.

  • Compreendendo a diferença entre os cursores Verdadeiro / Falso para Reciclagem . Esse pequeno sinalizador definido como verdadeiro pode tornar as ordens de execução de magnitude mais rápidas.
  • Coloque sua tabela no LoadOnlyMode para carregar dados. Por que atualizar o índice em cada inserção?
  • Entenda que, embora o IWorkspaceEdit :: StartEditing pareça o mesmo em todos os espaços de trabalho, eles são bestas muito diferentes em todas as fontes de dados. Em um Enterprise GDB, você pode ter controle de versão ou suporte para transações. Nos shapefiles, ele terá que ser implementado de uma maneira muito diferente. Como você implementaria Desfazer / Refazer? Você precisa ativá-lo (sim, isso pode fazer a diferença no uso da memória).
  • A diferença entre operações em lote ou operações de linha única. Caso em questão GetRow vs GetRows - esta é a diferença entre fazer uma consulta para obter uma linha ou fazer uma consulta para buscar várias linhas. Um loop apertado com uma chamada para GetRow significa desempenho horrível e é o culpado nº 1 de problemas de desempenho
  • Use UpdateSearchedRows
  • Entenda a diferença entre CreateRow e CreateRowBuffer . Enorme diferença no tempo de execução da inserção.
  • Entenda que IRow :: Store e IFeature :: Store disparam operações polimórficas super pesadas . Esta é provavelmente a razão # 2 culpada de desempenho realmente lento. Ele não salva apenas a linha, este é o método que garante que sua rede geométrica esteja correta, que o ArcMap Editor seja notificado de que uma linha foi alterada, que notifica todas as classes de relacionamento que têm algo a ver com essa linha validada para tornar verifique se a cardinalidade é válida etc. Você não deve inserir novas linhas com isso, deve usar um InsertCursor !
  • Deseja (precisa) fazer essas inserções em uma EditSession? Faz uma enorme diferença se você faz ou não. Algumas operações exigem isso (e tornam as coisas mais lentas), mas quando você não precisar, pule os recursos de desfazer / refazer.
  • Cursores são recursos caros. Depois de ter um identificador para um, você tem a garantia de que terá Consistência e Isolamento e que terá um custo.
  • Coloque em cache outros recursos, como conexões com o banco de dados (não crie e destrua sua referência da Área de Trabalho) e identificadores de Tabela (toda vez que você abrir ou fechar um - várias tabelas de metadados precisam ser lidas).
  • Colocar o FeatureClasses dentro ou fora de um FeatureDataset faz uma enorme diferença no desempenho. É não entende como um recurso organizacional!

5.E por último e não menos importante ...

Entenda a diferença entre operações de ligação de E / S e de CPU

Sinceramente, pensei em expandir mais cada um desses itens e talvez fazer uma série de entradas de blog que abrangem todos esses tópicos, mas a lista de pendências do meu calendário me deu um tapa na cara e começou a gritar comigo.

Meus dois centavos.

Ragi Yaser Burhum
fonte
5
obrigado. Eu deveria ter feito o trabalho em vez de escrever este haha pós
Ragi Yaser Burhum
3
+1 Muito obrigado pela sua contribuição, Sr. Burhum. Esse é o tipo de resposta que pretendia receber. Se eu pudesse votar duas vezes eu poderia !! O que os usuários do ArcGISScripting (python) devem tirar dessa resposta é que, embora os links reflitam os conceitos do ArcObjects e do .Net, os objetos COM subjacentes são os mesmos, entender esses objetos o ajudará a planejar melhor o código em qualquer idioma. Muita informação excelente aqui !!
OptimizePrime
1
@OptimizePrime Esse é um ótimo resumo. E você está certo - você não pode ignorar ArcObjects implicações se você quiser espremer desempenho de produtos ESRI
Ragi Yaser Burhum
1
obrigado, substituí store () por inserir cursores e economizei muito tempo em meus aplicativos!
superrache
5

Geralmente, para cálculos de desempenho, tento evitar o uso de qualquer material relacionado a ESRI. Para o seu exemplo, sugiro executar o processo em etapas, a primeira etapa lendo os dados em objetos python normais, os cálculos e a etapa final convertendo para o formato espacial ESRI final. Para ~ 10k registros, você provavelmente poderia armazenar tudo na memória para o processamento, o que daria um ganho definido de desempenho.

Anthony -GISCOE-
fonte
Obrigado pela sua resposta. É uma boa sugestão. Comecei a refatorar o código para executar os procedimentos necessários antes de usar o arcgisscripting. Depois de trabalhar com o software desde os dias de ArcInfo, acho frustrante o aumento do desempenho da CPU e do hardware, o desempenho do ArcGIS Map / Info / Editor XX fica estagnado. Talvez a introdução de GPUs possa impulsionar as coisas. Embora uma boa refactor da base de código ESRI pode ajudar também
OptimizePrime
1

Dependendo do hardware que você possui, você também pode considerar a opção exibida no Exemplo de geocoder da ESRI; fornece uma estrutura para separar um grande conjunto de dados e executar várias instâncias do python para oferecer uma abordagem quase multiencadeada. Vi o desempenho da geocodificação passar de 180.000 por hora em uma única instância do Python para mais de um milhão, graças à ativação de 8 processos paralelos na minha máquina.

Vi que, o máximo que posso, mantendo os dados no banco de dados e o trabalho funcional em minhas tabelas, e apenas o uso explícito de GIS no domínio ESRI proporcionam grandes aumentos de desempenho.

DEWright
fonte
Essas são ótimas ideias. Tenho a oportunidade de encadear alguns processos neste script, mas estou descobrindo que meus gargalos estão inicializando as bibliotecas COM e a E / S do Geodatabase. Em relação à E / S, reduzi a necessidade de uma única gravação. Se eu gastar mais tempo otimizando, meu chefe terá um ataque;) Então, estou deixando o threading como o último aperto de desempenho, se ele pedir mais. No momento, estou processando 60.000 recursos por minuto.
OptimizePrime
0

Você pode achar essas outras postagens no fórum interessantes, pois estão no contexto de otimização, mas para dados rasterizados e no geral:

Compilando scripts Python que usam as ferramentas de geoprocessamento do ArcGIS?

Tempo de processamento usando as ferramentas da caixa de ferramentas do ArcGIS Hydrology em script Python independente versus ArcCatalog?

a configuração gp.scratchworkspace fez uma grande diferença para mim em alguns códigos python que escrevi para delinear bacias hidrográficas.

Você poderia postar alguns exemplos de código que demonstram os números 1 e 2 em sua atualização para sua pergunta original? Eu ficaria interessado em ver a mecânica disso (embora eu assuma que você esteja lidando com dados de classe de recurso apenas aqui)

obrigado Tom

turkishgold
fonte