Um requisito comum no GIS é aplicar uma ferramenta de processamento a vários arquivos ou aplicar um processo a vários recursos de um arquivo a outro arquivo.
Muitas dessas operações são embaraçosamente paralelas, pois os resultados dos cálculos não influenciam em nenhuma outra operação do loop. Não apenas isso, mas frequentemente os arquivos de entrada são distintos.
Um exemplo clássico é o agrupamento de arquivos de forma contra arquivos que contêm polígonos para prendê-los.
Aqui está um método processual clássico (testado) para conseguir isso em um script python para QGIS. (fyi a saída de arquivos de memória temporários para arquivos reais mais da metade do tempo para processar meus arquivos de teste)
import processing
import os
input_file="/path/to/input_file.shp"
clip_polygons_file="/path/to/polygon_file.shp"
output_folder="/tmp/test/"
input_layer = QgsVectorLayer(input_file, "input file", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(input_layer)
tile_layer = QgsVectorLayer(clip_polygons_file, "clip_polys", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(tile_layer)
tile_layer_dp=input_layer.dataProvider()
EPSG_code=int(tile_layer_dp.crs().authid().split(":")[1])
tile_no=0
clipping_polygons = tile_layer.getFeatures()
for clipping_polygon in clipping_polygons:
print "Tile no: "+str(tile_no)
tile_no+=1
geom = clipping_polygon.geometry()
clip_layer=QgsVectorLayer("Polygon?crs=epsg:"+str(EPSG_code)+\
"&field=id:integer&index=yes","clip_polygon", "memory")
clip_layer_dp = clip_layer.dataProvider()
clip_layer.startEditing()
clip_layer_feature = QgsFeature()
clip_layer_feature.setGeometry(geom)
(res, outFeats) = clip_layer_dp.addFeatures([clip_layer_feature])
clip_layer.commitChanges()
clip_file = os.path.join(output_folder,"tile_"+str(tile_no)+".shp")
write_error = QgsVectorFileWriter.writeAsVectorFormat(clip_layer, \
clip_file, "system", \
QgsCoordinateReferenceSystem(EPSG_code), "ESRI Shapefile")
QgsMapLayerRegistry.instance().addMapLayer(clip_layer)
output_file = os.path.join(output_folder,str(tile_no)+".shp")
processing.runalg("qgis:clip", input_file, clip_file, output_file)
QgsMapLayerRegistry.instance().removeMapLayer(clip_layer.id())
Isso seria bom, exceto que meu arquivo de entrada tem 2 GB e o arquivo de recorte de polígono contém mais de 400 polígonos. O processo resultante leva mais de uma semana na minha máquina quad core. Enquanto isso, três núcleos estão ociosos.
A solução que tenho em minha cabeça é exportar o processo para arquivos de script e executá-los de forma assíncrona usando o gnu paralelo, por exemplo. No entanto, parece uma pena ter que abandonar o QGIS em uma solução específica do SO, em vez de usar algo nativo do python do QGIS. Então, minha pergunta é:
Posso paralelizar operações geográficas embaraçosamente paralelas nativamente dentro do python QGIS?
Caso contrário, talvez alguém já tenha o código para enviar esse tipo de trabalho para scripts shell assíncronos?
fonte
Respostas:
Se você alterar o seu programa para ler o nome do arquivo na linha de comando e dividir o arquivo de entrada em partes menores, poderá fazer algo parecido com isso usando o GNU Parallel:
Isso executará 1 trabalho por núcleo.
Todos os novos computadores possuem múltiplos núcleos, mas a maioria dos programas é de natureza serial e, portanto, não usa os múltiplos núcleos. No entanto, muitas tarefas são extremamente paralelizáveis:
O GNU Parallel é um paralelizador geral e facilita a execução de trabalhos em paralelo na mesma máquina ou em várias máquinas às quais você tem acesso ssh.
Se você tiver 32 tarefas diferentes que deseja executar em 4 CPUs, uma maneira direta de paralelizar é executar 8 tarefas em cada CPU:
O GNU Parallel gera um novo processo quando se termina - mantendo as CPUs ativas e economizando tempo:
Instalação
Se o GNU Parallel não estiver empacotado para sua distribuição, você poderá fazer uma instalação pessoal, que não requer acesso root. Isso pode ser feito em 10 segundos, fazendo o seguinte:
Para outras opções de instalação, consulte http://git.savannah.gnu.org/cgit/parallel.git/tree/README
Saber mais
Veja mais exemplos: http://www.gnu.org/software/parallel/man.html
Assista aos vídeos de introdução: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Percorra o tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html
Inscreva-se na lista de e-mails para obter suporte: https://lists.gnu.org/mailman/listinfo/parallel
fonte
my_processing.py
pode ser encontrada em gis.stackexchange.com/a/130337/26897Em vez de usar o método GNU Parallel, você pode usar o módulo mutliprocess python para criar um conjunto de tarefas e executá-las. Não tenho acesso a uma configuração do QGIS para testá-lo, mas o multiprocesso foi adicionado no Python 2.6, desde que você esteja usando o 2.6 ou posterior, pois ele deve estar disponível. Existem muitos exemplos online sobre o uso deste módulo.
fonte
Aqui está a solução paralela gnu. Com algum cuidado, a maioria dos algoritmos ogr ou saga baseados em linux, paralelamente surpreendentemente paralelos, podem ser executados com ele dentro da instalação do QGIS.
Obviamente, esta solução requer a instalação do gnu paralelo. Para instalar o gnu paralelo no Ubuntu, por exemplo, vá ao seu terminal e digite
NB: Não consegui que o comando shell paralelo funcionasse no Popen ou no subprocesso, o que eu preferiria, então cortei uma exportação para um script bash e executei com o Popen.
Aqui está o comando shell específico usando paralelo que envolvi em python
Cada {1} é trocado por um número do intervalo {1..400} e os quatrocentos comandos do shell são gerenciados pelo gnu paralelamente para usar simultaneamente todos os núcleos do meu i7 :).
Aqui está o código python real que escrevi para resolver o problema de exemplo que publiquei. Pode-se colá-lo diretamente após o final do código na pergunta.
Deixe-me dizer-lhe que é realmente algo quando você vê todos os núcleos dispararem com ruído total :). Agradecimentos especiais a Ole e à equipe que construiu o Gnu Parallel.
Seria bom ter uma solução de plataforma cruzada e seria bom se eu pudesse descobrir o módulo python de multiprocessamento para o python incorporado qgis, mas, infelizmente, não deveria ser.
Independentemente desta solução vai me servir e talvez você muito bem.
fonte