PyQGIS में समानांतर जीआईएस संचालन?


15

जीआईएस में एक सामान्य आवश्यकता एक प्रोसेसिंग टूल को कई फाइलों में लगाने या एक फाइल में एक फाइल में दूसरी सुविधाओं के लिए एक प्रक्रिया लागू करने की है।

इनमें से अधिकांश ऑपरेशन शर्मनाक रूप से समानांतर हैं कि गणना के परिणाम किसी भी तरह से लूप में किसी अन्य ऑपरेशन को प्रभावित नहीं करते हैं। इतना ही नहीं बल्कि अक्सर इनपुट फाइलें प्रत्येक विशिष्ट होती हैं।

बिंदु में एक क्लासिक मामला है, फाइलों को पॉलीगनों से युक्त करने के लिए उनके खिलाफ क्लिप करने के लिए आकार की फाइलों के बाहर टाइलिंग।

QGIS के लिए एक पायथन स्क्रिप्ट में इसे प्राप्त करने के लिए एक (परीक्षण) शास्त्रीय प्रक्रियात्मक विधि है। (मेरी परीक्षण फ़ाइलों को संसाधित करने के लिए समय से अधिक रोक दी गई वास्तविक फ़ाइलों के लिए अस्थायी मेमोरी फ़ाइलों का आउटपुट फी)

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

यह ठीक होगा सिवाय इसके कि मेरी इनपुट फ़ाइल 2GB है और बहुभुज क्लिपिंग फ़ाइल में 400+ पॉलीगॉन हैं। परिणामी प्रक्रिया को मेरी क्वाड कोर मशीन पर एक सप्ताह से अधिक समय लगता है। जबकि सभी तीन कोर सिर्फ सुस्ती हैं।

मेरे पास जो समाधान मेरे सिर में है, वह प्रक्रिया को स्क्रिप्ट फ़ाइलों में निर्यात करने और उदाहरण के लिए ग्नू समानांतर का उपयोग करते हुए उन्हें अतुल्यकालिक रूप से चलाने के लिए है। हालाँकि यह QGIS से बाहर निकलने के लिए एक OS विशिष्ट समाधान में QGIS से बाहर निकलने के लिए शर्म की बात है, QGIS अजगर के लिए कुछ देशी का उपयोग करें। तो मेरा सवाल है:

क्या मैं अजगर QGIS के अंदर शर्मनाक ढंग से समानांतर भौगोलिक संक्रियाओं को समानांतर कर सकता हूं?

यदि नहीं, तो शायद किसी के पास पहले से ही अतुल्यकालिक खोल लिपियों के लिए इस तरह के काम को भेजने के लिए कोड है?


QGIS में मल्टीप्रोसेसिंग से परिचित नहीं है, लेकिन यह आर्कगिस-विशिष्ट उदाहरण कुछ उपयोग का हो सकता है: gis.stackexchange.com/a/20352/753
blah238

दिलचस्प लग रहा है। मैं देखूंगा कि मैं इसके साथ क्या कर सकता हूं।
मि। पर्पल

जवाबों:


11

यदि आप कमांड लाइन से फ़ाइल का नाम पढ़ने के लिए अपना प्रोग्राम बदलते हैं और अपनी इनपुट फ़ाइल को छोटे-छोटे खंडों में विभाजित करते हैं, तो आप GNU समानांतर का उपयोग करके कुछ ऐसा कर सकते हैं:

parallel my_processing.py {} /path/to/polygon_file.shp ::: input_files*.shp

यह प्रति कोर 1 नौकरी चलाएगा।

सभी नए कंप्यूटरों में एकाधिक कोर होते हैं, लेकिन अधिकांश प्रोग्राम प्रकृति में धारावाहिक होते हैं और इसलिए एकाधिक कोर का उपयोग नहीं करेंगे। हालाँकि, कई कार्य अत्यंत समांतर हैं:

  • कई फाइलों पर एक ही प्रोग्राम चलाएं
  • किसी फ़ाइल में प्रत्येक पंक्ति के लिए समान प्रोग्राम चलाएँ
  • किसी फ़ाइल में प्रत्येक ब्लॉक के लिए एक ही प्रोग्राम चलाएँ

जीएनयू समानांतर एक सामान्य समांतरक है और इससे एक ही मशीन पर या आपके द्वारा उपयोग की जाने वाली कई मशीनों पर समानांतर में नौकरी चलाना आसान हो जाता है।

यदि आपके पास 32 अलग-अलग नौकरियां हैं जो आप 4 सीपीयू पर चलाना चाहते हैं, तो समानांतर करने के लिए एक सीधा आगे का तरीका प्रत्येक सीपीयू पर 8 नौकरियों को चलाना है:

सरल समय-निर्धारण

जीएनयू समानांतर इसके बजाय एक नई प्रक्रिया को जन्म देता है जब एक खत्म हो जाता है - सीपीयू को सक्रिय रखना और इस तरह समय की बचत करना:

GNU समानांतर शेड्यूलिंग

स्थापना

यदि जीएनयू समानांतर आपके वितरण के लिए पैक नहीं किया गया है, तो आप एक व्यक्तिगत स्थापना कर सकते हैं, जिसे रूट एक्सेस की आवश्यकता नहीं है। इसे 10 सेकंड में किया जा सकता है:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

अन्य संस्थापन विकल्पों के लिए देखें http://git.savannah.gnu.org/cgit/parallel.git/tree/README

और अधिक जानें

और उदाहरण देखें: http://www.gnu.org/software/parallel/man.html

इंट्रो वीडियो देखें: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

ट्यूटोरियल के माध्यम से चलें: http://www.gnu.org/software/parallel/parallel_tutorial.html

समर्थन पाने के लिए ईमेल सूची के लिए साइन अप करें: https://lists.gnu.org/mailman/listinfo/parallel


यह कुछ ऐसा है जैसे मैं कोशिश और प्रयास करने जा रहा था, लेकिन मुझे अजगर के अंदर रहने की जरूरत है। उदाहरण के लिए पोपेन का उपयोग करने के लिए लाइन को फिर से लिखने की आवश्यकता है ... कुछ इस तरह: उपप्रकार के आयात से पॉपेन, पीआईपीई पी = पोपेन (["समानांतर", "ऑग्रेगोग्र", "- क्लिपस्कैप", "क्लिप_फाइल *। एसपीपी", "आउटपुट"। .shp "input.shp"], stdin = PIPE, stdout = PIPE, stderr = PIPE) समस्या यह है कि मुझे अभी तक पता नहीं है कि वाक्यविन्यास को ठीक से कैसे तैयार किया जाए
श्रीमान पर्पल

बहुत बढ़िया जवाब। मैं पहले ट्रिपल (या चौगुनी) औपनिवेशिक संचालकों के सामने नहीं आया था (हालांकि मैं वर्तमान में edX पर हास्केल मॉक कर रहा हूं, इसलिए इसमें कोई संदेह नहीं है कि कुछ ऐसा ही होगा)। मैं आपके साथ संता, भूत, परियों और देवताओं के बारे में सहमत हूं, लेकिन निश्चित रूप से नहीं: गोबल्स: डी
जॉन पॉवेल

@MrPurple मुझे लगता है कि टिप्पणी वारंट को अपने आप में एक प्रश्न बनाती है। जवाब निश्चित रूप से एक टिप्पणी में डालने के लिए बहुत लंबा है।
ओले तांगे

ठीक है, लिंक के लिए धन्यवाद। अगर मैं गन्न समानांतर का उपयोग करके एक उत्तर तैयार करता हूं तो मैं इसे यहां पोस्ट करूंगा।
श्री पर्पल

आपके लिए एक अच्छा सूत्रीकरण gis.stackexchange.com/a/130337/26897my_processing.py पर पाया जा सकता है
श्रीमान बैंगनी

4

जीएनयू समानांतर पद्धति का उपयोग करने के बजाय आप कार्यों का एक पूल बनाने और उन्हें क्रियान्वित करने के लिए अजगर उत्परिवर्तजन मॉड्यूल का उपयोग कर सकते हैं। मेरे पास इसका परीक्षण करने के लिए QGIS सेटअप तक पहुंच नहीं है, लेकिन Python 2.6 में मल्टीप्रोसेस को जोड़ा गया, ताकि आप 2.6 का उपयोग कर रहे हों या बाद में यह उपलब्ध हो। इस मॉड्यूल का उपयोग करने पर ऑनलाइन बहुत सारे उदाहरण हैं।


2
मैंने मल्टीप्रोसेस को एक बार दिया लेकिन मुझे अभी तक इसे QGIS के एम्बेडेड अजगर में सफलतापूर्वक देखने के लिए मिला है। मैंने कई मुद्दों को मारा जैसा कि मैंने इसे आजमाया। मैं उन्हें अलग प्रश्नों के रूप में पोस्ट कर सकता हूं। जहाँ तक मैं बता सकता हूँ कि इस के साथ शुरू होने वाले किसी भी सार्वजनिक उदाहरण सुलभ नहीं हैं।
मि। पर्पल

यह वाकई शर्म की बात है। अगर कोई मल्टीपर्स मॉड्यूल का एक उदाहरण लिख सकता है, जो एकल pyQGIS फ़ंक्शन को लपेटता है जैसा कि मैंने ग्नू समानांतर के साथ किया था, तो हम सभी को बंद कर सकते हैं और जो कुछ भी हम चुनते हैं उसे समानांतर कर सकते हैं।
मि। पर्पल

मैं सहमत हूं लेकिन जैसा कि मैंने कहा कि फिलहाल मेरे पास QGIS तक पहुंच नहीं है।
स्टीव बार्न्स 23


@MrPurple और यह एक gis.stackexchange.com/questions/114260/… एक उदाहरण देता है
स्टीव बार्न्स

3

यहाँ गन्न समानांतर समाधान है। कुछ देखभाल के साथ सबसे अधिक स्पष्ट रूप से समानांतर लिनक्स आधारित ओगर या गाथा एल्गोरिदम को आपके क्यूजीआर इंस्टॉलेशन के अंदर इसके साथ चलाने के लिए बनाया जा सकता है।

स्पष्ट रूप से इस समाधान में समानांतर रूप से गन्न की स्थापना की आवश्यकता है। उदाहरण के लिए, उबंटू में समानांतर रूप से गन्नू स्थापित करने के लिए, अपने टर्मिनल पर जाएं और टाइप करें

sudo apt-get -y install parallel

NB: मुझे पोपेन या उपप्रोसेस में काम करने के लिए समानांतर शेल कमांड नहीं मिल सकती थी, जिसे मैं पसंद करता, इसलिए मैंने एक बैश स्क्रिप्ट के लिए एक निर्यात को एक साथ हैक किया और इसके बजाय पॉपेन के साथ भाग गया।

यहाँ विशिष्ट शेल कमांड का उपयोग समानांतर है जो मैंने अजगर में लपेटा है

parallel ogr2ogr -skipfailures -clipsrc tile_{1}.shp output_{1}.shp input.shp ::: {1..400}

प्रत्येक {1} {1..400} रेंज से एक नंबर के लिए स्वैप किया जाता है और फिर चार सौ शेल कमांड्स को मेरे i7 :) के सभी कोर का समवर्ती उपयोग करने के लिए gnu के समानांतर प्रबंधित किया जाता है।

यहाँ वास्तविक अजगर कोड है जिसे मैंने अपने द्वारा पोस्ट की गई उदाहरण समस्या को हल करने के लिए लिखा था। एक प्रश्न में कोड के अंत के बाद सीधे इसे पेस्ट कर सकता है।

import stat
from subprocess import Popen
from subprocess import PIPE
feature_count=tile_layer.dataProvider().featureCount()
subprocess_args=["parallel", \
"ogr2ogr","-skipfailures","-clipsrc",\
os.path.join(output_folder,"tile_"+"{1}"+".shp"),\
os.path.join(output_folder,"output_"+"{1}"+".shp"),\
input_file,\
" ::: ","{1.."+str(feature_count)+"}"]
#Hacky part where I write the shell command to a script file
temp_script=os.path.join(output_folder,"parallelclip.sh")
f = open(temp_script,'w')
f.write("#!/bin/bash\n")
f.write(" ".join(subprocess_args)+'\n')
f.close()
st = os.stat(temp_script)
os.chmod(temp_script, st.st_mode | stat.S_IEXEC)
#End of hacky bash script export
p = Popen([os.path.join(output_folder,"parallelclip.sh")],\
stdin=PIPE, stdout=PIPE, stderr=PIPE)
#Below is the commented out Popen line I couldn't get to work
#p = Popen(subprocess_args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode
print output
print err

#Delete script and old clip files
os.remove(os.path.join(output_folder,"parallelclip.sh"))
for i in range(feature_count):
    delete_file = os.path.join(output_folder,"tile_"+str(i+1)+".shp")
    nosuff=os.path.splitext(delete_file)[0]
    suffix_list=[]
    suffix_list.append('.shx')
    suffix_list.append('.dbf')
    suffix_list.append('.qpj')
    suffix_list.append('.prj')
    suffix_list.append('.shp')
    suffix_list.append('.cpg')
    for suffix in suffix_list:
        try:
            os.remove(nosuff+suffix)
        except:
            pass

आपको बता दें कि यह वास्तव में कुछ है जब आप देखते हैं कि सभी कोर पूर्ण शोर तक आग करते हैं :)। ओले और उस टीम के लिए विशेष धन्यवाद जिसने गन्न समानांतर बनाया।

क्रॉस प्लेटफॉर्म सॉल्यूशन रखना अच्छा होगा और यह अच्छा होगा अगर मैं क्यूगिस एम्बेडेड अजगर के लिए मल्टीप्रोसेसिंग पाइथन मॉड्यूल का पता लगा सकता था लेकिन अफसोस कि ऐसा होना नहीं था।

भले ही यह समाधान मेरी सेवा करेगा और शायद आप अच्छी तरह से करेंगे।


स्पष्ट रूप से किसी को कोड के पहले टुकड़े में "प्रोसेसिंग.runalg" लाइन पर टिप्पणी करनी चाहिए ताकि क्लिप समानांतर में चलने से पहले क्रमिक रूप से पहले न चले। इसके अलावा यह सवाल में कोड के नीचे जवाब से कोड को कॉपी और पेस्ट करने की बात है।
मि। पर्पल

"QGIS: भंग" तुम सिर्फ का एक सेट की तरह आदेशों प्रसंस्करण के बहुत सारे चलाना चाहते हैं तो समानांतर में अलग फ़ाइलों के लिए आवेदन किया तो आप पर इस बात के लिए मेरी प्रक्रिया को देख सकते हैं purplelinux.co.nz/?p=190
श्री बैंगनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.