अद्वितीय आउटपुट फ़ाइलों के लिए अद्वितीय इनपुट फ़ाइलों को संसाधित करने के लिए समानांतर का उपयोग करना


18

मुझे एक शेल स्क्रिप्टिंग समस्या है, जहां मुझे इनपुट फ़ाइलों से भरी निर्देशिका दी गई है (प्रत्येक फ़ाइल जिसमें कई इनपुट लाइनें हैं), और मुझे उन्हें व्यक्तिगत रूप से संसाधित करने की आवश्यकता है, उनके प्रत्येक आउटपुट को एक अद्वितीय फ़ाइल (उर्फ, file_1.input) की आवश्यकता है file_1.output में कैप्चर किया जाना है, और इसी तरह)।

पूर्व-समानांतर , मैं बस निर्देशिका में प्रत्येक फ़ाइल पर पुनरावृति करूंगा और प्रोसेसर को अभिभूत नहीं करने के लिए टाइमर / गिनती तकनीक के कुछ प्रकार करते हुए अपनी कमांड का प्रदर्शन करता हूं (यह मानते हुए कि प्रत्येक प्रक्रिया में एक निरंतर रनटाइम था)। हालाँकि, मुझे पता है कि हमेशा ऐसा नहीं होगा, इसलिए समाधान की तरह "समानांतर" का उपयोग करना कस्टम कोड लिखने के बिना शेल स्क्रिप्ट मल्टी-थ्रेडिंग प्राप्त करने का सबसे अच्छा तरीका है।

जबकि मैंने इनमें से प्रत्येक फ़ाइल को संसाधित करने के लिए समानांतर रूप से कोड़ा मारने के बारे में सोचा है (और मुझे अपने कोर को कुशलतापूर्वक प्रबंधित करने की अनुमति देता है), वे सभी हैकिंग लगते हैं। मुझे लगता है कि मुझे लगता है कि यह एक बहुत ही आसान उपयोग मामला है, इसलिए इसे जितना संभव हो उतना साफ रखना पसंद करेंगे (और समानांतर उदाहरणों में कुछ भी मेरी समस्या के रूप में बाहर नहीं लगता है।

किसी भी सहायता की सराहना की जाएगी!

इनपुट निर्देशिका उदाहरण:

> ls -l input_files/
total 13355
location1.txt
location2.txt
location3.txt
location4.txt
location5.txt

स्क्रिप्ट:

> cat proces_script.sh
#!/bin/sh

customScript -c 33 -I -file [inputFile] -a -v 55 > [outputFile]

अद्यतन : ओले के जवाब को नीचे पढ़ने के बाद, मैं अपने स्वयं के समानांतर कार्यान्वयन के लिए लापता टुकड़ों को एक साथ रखने में सक्षम था। हालांकि उनका जवाब बहुत अच्छा है, यहाँ मेरे अतिरिक्त शोध और नोट्स हैं जिन्हें मैंने लिया:

अपनी पूरी प्रक्रिया को चलाने के बजाय, मैंने अपने वातावरण में उनके समाधान को साबित करने के लिए कॉन्सेप्ट कमांड के प्रमाण के साथ शुरुआत की। मेरे दो अलग कार्यान्वयन (और नोट) देखें:

find /home/me/input_files -type f -name *.txt | parallel cat /home/me/input_files/{} '>' /home/me/output_files/{.}.out

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

parallel cat '>' /home/me/output_files/{.}.out :::  /home/me/input_files/*

यह दूसरा समाधान समानांतर फ़ाइलों के समानांतर प्रतिमान का उपयोग करता है, जिसमें फ़ाइलों को पढ़ने के लिए, हालांकि एक नौसिखिया के लिए, यह बहुत अधिक भ्रमित था। मेरे लिए, फाइंड ए और पाइप का उपयोग करके मेरी जरूरतों को पूरा किया गया।

जवाबों:


27

GNU समानांतर इस तरह के कार्यों के लिए डिज़ाइन किया गया है:

parallel customScript -c 33 -I -file {} -a -v 55 '>' {.}.output ::: *.input

या:

ls | parallel customScript -c 33 -I -file {} -a -v 55 '>' {.}.output

यह प्रति सीपीयू कोर में एक नौकरी चलाएगा।

आप केवल द्वारा GNU समानांतर स्थापित कर सकते हैं:

wget https://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

अधिक जानने के लिए GNU समानांतर के इंट्रो वीडियो देखें: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


महान उत्तर (और समानांतर का उपयोग करने के मेरे अनुरोध को पढ़ने के लिए प्रमुख बिंदु)।
जे जोन्स

5

ऐसा करने का मानक तरीका यह है कि किसी पंक्ति को सेटअप करें और किसी भी संख्या में श्रमिकों को स्पान दें जो जानते हैं कि कतार से कुछ कैसे खींचना है और इसे कैसे संसाधित करना है। आप इन प्रक्रियाओं के बीच संचार के लिए एक पानो (उर्फ नामित पाइप) का उपयोग कर सकते हैं।

नीचे अवधारणा को प्रदर्शित करने के लिए एक भोला उदाहरण है।

एक सरल कतार स्क्रिप्ट:

#!/bin/sh
mkfifo /tmp/location-queue
for i in inputfiles/*; do
  echo $i > /tmp/location-queue
done
rm /tmp/location-queue

और एक कार्यकर्ता:

#!/bin/sh
while read file < /tmp/location-queue; do
  process_file "$file"
done

process_file आपके कार्यकर्ता में कहीं भी परिभाषित किया जा सकता है, और इसे करने के लिए आपको जो कुछ भी ज़रूरत है वह कर सकता है।

एक बार जब आपके पास दो टुकड़े हो जाते हैं, तो आपके पास एक सरल मॉनिटर हो सकता है जो कतार प्रक्रिया और किसी भी श्रमिक प्रक्रिया को शुरू करता है।

मॉनिटर स्क्रिप्ट:

#!/bin/sh
queue.sh &
num_workers="$1"
i=0
while [ $i < $num_workers ]; do
  worker.sh &
  echo $! >> /tmp/worker.pids
  i=$((i+1))
done
monitor_workers

ये लो। यदि आप वास्तव में ऐसा करते हैं, तो मॉनिटर में फ़ेनो को सेटअप करना बेहतर है, और कतार और श्रमिकों दोनों के लिए मार्ग पास करें, इसलिए वे युग्मित नहीं होते हैं और फ़ेडो के लिए किसी विशिष्ट स्थान पर नहीं अटकते हैं। मैंने इसे इस तरीके से उत्तर में विशेष रूप से सेट किया है, इसलिए यह स्पष्ट है कि आप इसे पढ़ते समय क्या उपयोग कर रहे हैं।


मॉनीटर कैसे स्मार्ट हो जाता है जब तक कि अगले काम को पूरा करने के लिए नए कर्मचारियों को रोक दिया जाता है (उर्फ, जहां मैं कभी भी डीक्रिएट नहीं करता)? ---- अपने स्वयं के संपादन का जवाब देते हुए, कार्यकर्ता कभी दूर नहीं जाते हैं, वे बस फाइलों को संसाधित करते हैं जब तक कि सभी प्रसंस्करण समाप्त नहीं हो जाते हैं (इसलिए 'प्रोसेसर' के भीतर लूप भी)।
J जोन्स

मॉनिटर स्क्रिप्ट के प्रदर्शन के अंत में "मॉनिटर_वर्कर्स" लाइन क्या है?
J जोन्स

@JJones - monitor_workersजैसा है process_file- यह एक ऐसा फंक्शन है, जो आप चाहते हैं। मॉनिटर के बारे में - आप सही थे; इसे अपने श्रमिकों की पीडि़तों को बचाना चाहिए (इसलिए यह एक किल सिग्नल भेज सकता है) और जब यह एक कार्यकर्ता शुरू करता है तो काउंटर को बढ़ाने की आवश्यकता होती है। मैंने इसमें शामिल होने का उत्तर संपादित किया है।
शॉन जे। गोफ

मैं वास्तव में आपके काम की सराहना करता हूं, लेकिन मुझे लगता है कि आपको जीएनयू का उपयोग करना चाहिए parallel। मुझे लगता है कि यह आपका विचार है, पूरी तरह से लागू किया गया है।
motobói

5

एक और उदाहरण:

ls *.txt | parallel 'sort {} > {.}.sorted.txt'

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


4

एक सामान्य रूप से उपलब्ध उपकरण जो समानांतर कर सकता है, वह है। जीएनयू बनाते हैं और कुछ अन्य लोगों के पास -jसमानांतर निर्माण करने का एक विकल्प होता है।

.SUFFIXES: .input .output
.input.output:
        process_one_file <$< >$@.tmp
        mv -f $@.tmp $@

makeइस तरह से चलाएं (मुझे लगता है कि आपके फ़ाइल नामों में कोई विशेष वर्ण नहीं है, makeउन लोगों के साथ अच्छा नहीं है):

make -j 4 $(for x in *.input; do echo ${x%.*}.output; done)

imho यह सबसे चतुर उपाय है :)
h4unt3r

3

यह वर्तमान निर्देशिका में फ़ाइलों के एक बड़े सेट पर एक ही कमांड निष्पादित करने के लिए है:

#!/bin/sh
trap 'worker=`expr $worker - 1`' USR1  # free up a worker
worker=0  # current worker
num_workers=10  # maximum number of workers
for file in *.txt; do
    if [ $worker -lt $num_workers ]; then
        {   customScript -c 33 -I -file $file -a -v 55 > `basename $file .txt`.outtxt 
            kill -USR1 $$ 2>/dev/null  # signal parent that we're free
        } &
        echo $worker/$num_worker $! $file  # feedback to caller
        worker=`expr $worker + 1`
    else
        wait # for a worker to finish
    fi
done

यह फाइलों में आउटपुट डालकर, customScriptप्रत्येक txtफाइल पर चलता है outtxt। अपनी जरूरत के अनुसार बदलें। यह काम करने के लिए महत्वपूर्ण है सिग्नल प्रोसेसिंग, SIGUSR1 का उपयोग करके ताकि बच्चे की प्रक्रिया माता-पिता की प्रक्रिया को बता सके कि यह किया जाता है। SIGCHLD का उपयोग करना काम नहीं करेगा क्योंकि स्क्रिप्ट में अधिकांश स्टेटमेंट शेल स्क्रिप्ट में SIGCHLD सिग्नल उत्पन्न करेगा। मैंने आपके कमांड को बदलने की कोशिश की sleep 1, इस प्रोग्राम में 0.28s उपयोगकर्ता cpu और 0.14s सिस्टम cpu का उपयोग किया गया; यह केवल लगभग 400 फाइलों पर था।


'वेट' कैसे स्मार्ट है जो एक ही फाइल को लेने के लिए पर्याप्त है जो वर्तमान में पुनरावृत्त हो रही है और "स्टेटिंग" में फिर से दर्ज करें यदि "स्टेटमेंट"?
जे जोन्स

ऐसा नहीं है waitकि 'स्मार्ट' पर्याप्त है; लेकिन यह SIGUSR1संकेत मिलने के बाद वापस आ जाएगा । बच्चा / कार्यकर्ता SIGUSR1माता-पिता को भेजता है , जो पकड़ा जाता है ( trap), और डिक्रीमेंट $worker( trapखंड) और असामान्य रूप से वापस आता है wait, जिससे if [ $worker -lt $num_workers ]खंड निष्पादित हो सके।
13

0

या बस का उपयोग करें xargs -P, additonal सॉफ्टवेयर स्थापित करने की कोई जरूरत नहीं:

find . -type f -print0 | xargs -0 -I'XXX' -P4 -n1 custom_script -input "XXX" -output "XXX.out"

विकल्पों के लिए थोड़ा स्पष्टीकरण:

  • -I'XXX' स्ट्रिंग को फ़ाइल नाम के साथ कमांड टेम्पलेट में बदल दिया जाएगा
  • -P4 समानांतर में 4 प्रक्रियाएं चलाएगा
  • -n1 भले ही दो एक्सएक्सएक्स पाए जाने पर प्रति निष्पादन केवल एक फ़ाइल डाल दी जाएगी
  • -print0और -0एक साथ काम करते हैं, जिससे आपको फ़ाइल नामों में विशेष वर्ण (जैसे व्हॉट्सएप) मिलते हैं
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.