समानांतर में चार कार्य ... मैं कैसे करूँ?


23

मैं एक निर्देशिका पर PNG छवियों का एक गुच्छा है। मेरे पास एक एप्लिकेशन है जिसे pngout कहा जाता है जिसे मैं इन चित्रों को संपीड़ित करने के लिए चलाता हूं। इस एप्लिकेशन को एक स्क्रिप्ट द्वारा बुलाया जाता है। समस्या यह है कि यह स्क्रिप्ट एक समय में एक करता है, कुछ इस तरह से:

FILES=(./*.png)
for f in  "${FILES[@]}"
do
        echo "Processing $f file..."
        # take action on each file. $f store current file name
        ./pngout -s0 $f R${f/\.\//}
done

एक समय में सिर्फ एक फ़ाइल को संसाधित करने में बहुत समय लगता है। इस ऐप को चलाने के बाद, मैं देखता हूं कि सीपीयू सिर्फ 10% है। इसलिए मुझे पता चला कि मैं इन फ़ाइलों को 4 बैचों में विभाजित कर सकता हूं, प्रत्येक बैच को एक निर्देशिका में रख सकता हूं और 4 को चार टर्मिनल विंडो, चार प्रक्रियाओं से फायर कर सकता हूं, इसलिए मेरी स्क्रिप्ट के चार उदाहरण हैं, एक ही समय में, उन छवियों को संसाधित करना और नौकरी में 1/4 समय लगता है।

दूसरी समस्या यह है कि मैंने छवियों और बैचों को विभाजित करने और चार निर्देशिकाओं को स्क्रिप्ट की प्रतिलिपि बनाने में समय खो दिया, 4 टर्मिनल विंडो खोलें, ब्ला ब्ला ...

कैसे एक स्क्रिप्ट के साथ, कुछ भी विभाजित किए बिना?

मेरा मतलब दो चीजों से है: पहले मैं एक बैश स्क्रिप्ट से कैसे करूँ, पृष्ठभूमि के लिए एक प्रक्रिया आग? (बस जोड़ें और अंत तक?) दूसरा: मैं चौथे कार्यों को भेजने के बाद पृष्ठभूमि पर कार्य भेजना कैसे बंद कर दूं और कार्य समाप्त होने तक प्रतीक्षा करने के लिए स्क्रिप्ट डालूं? मेरा मतलब है, बस एक कार्य को पृष्ठभूमि में एक कार्य के रूप में भेजना, हमेशा 4 कार्यों को समानांतर में रखना? अगर मैं यह नहीं करता कि पाश पृष्ठभूमि के कार्यों के zillions को आग लगा देगा और CPU बंद हो जाएगा।


जवाबों:


33

यदि आपके पास उस की एक प्रति है xargsजो समानांतर निष्पादन का समर्थन करती है -P, तो आप बस कर सकते हैं

printf '%s\0' *.png | xargs -0 -I {} -P 4 ./pngout -s0 {} R{}

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


2
इस मामले के लिए डिज़ाइन किए गए "ग्नू समानांतर" और "xjobs" भी हैं। यह ज्यादातर स्वाद का मामला है जिसे आप पसंद करते हैं।
wnoise

क्या आप प्रस्तावित आदेश की व्याख्या कर सकते हैं? धन्यवाद!
यूजीन एस

1
@EugeneS क्या भाग के बारे में थोड़ा और अधिक विशिष्ट हो सकता है? प्रिंटफ सभी पीएनजी फाइलों को इकट्ठा करता है और उन्हें एक पाइप के माध्यम से xargs में भेजता है, जो मानक इनपुट से तर्क एकत्र करता है और उन्हें उन तर्कों में जोड़ता है, जो pngoutओपी चलाना चाहते थे। मुख्य विकल्प है -P 4, जो xargs को 4 समवर्ती कमांड का उपयोग करने के लिए कहता है।
jw013

2
सटीक नहीं होने के लिए क्षमा करें। मुझे विशेष रूप से दिलचस्पी थी कि आपने printfकेवल नियमित के बजाय यहां फ़ंक्शन का उपयोग क्यों किया ls .. | grep .. *.png? इसके अलावा, मैं xargsआपके ( -0और -I{}) इस्तेमाल किए गए मापदंडों में दिलचस्पी रखता था । धन्यवाद!
यूजीन एस

3
@ यूजीनस यह अधिकतम शुद्धता और मजबूती के लिए है। फ़ाइल नाम लाइनें नहीं हैं, और lsइसे फ़ाइलनाम को पार्स और सुरक्षित रूप से पार्स करने के लिए उपयोग नहीं किया जा सकता है । फ़ाइल नामों को सीमांकित करने के लिए उपयोग किए जाने वाले एकमात्र सुरक्षित वर्ण हैं \0और /, चूंकि प्रत्येक अन्य वर्ण, \nफ़ाइल नाम का ही हिस्सा हो सकता है। printfका उपयोग करता है \0परिसीमित फ़ाइल नाम के लिए, और -0सूचित xargsइस की। -I{}बताता है xargsको बदलने के लिए {}तर्क के साथ।
jw013

8

पहले से प्रस्तावित समाधानों के अलावा, आप एक ऐसा मेकफाइल बना सकते हैं, जो बताता है कि कैसे असम्पीडित से एक संपीड़ित फ़ाइल बनाने के लिए, और make -j 4समानांतर में 4 नौकरियों को चलाने के लिए उपयोग करें। समस्या यह है कि आपको संपीड़ित और असम्पीडित फ़ाइलों को अलग-अलग नाम देना होगा या उन्हें अलग-अलग निर्देशिकाओं में संग्रहीत करना होगा, अन्यथा एक उचित नियम बनाना असंभव होगा।


7

यदि आपके पास GNU समानांतर http://www.gnu.org/software/parallel/ स्थापित है, तो आप ऐसा कर सकते हैं:

parallel ./pngout -s0 {} R{} ::: *.png

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

wget http://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

आपके दो सवालों के जवाब देने के लिए:

  • हाँ, लाइन के अंत में जोड़ना और खोलना आपको पृष्ठभूमि प्रक्रिया शुरू करने का निर्देश देगा।
  • waitकमांड का उपयोग करके , आप शेल को आगे बढ़ने से पहले पृष्ठभूमि की सभी प्रक्रियाओं के लिए प्रतीक्षा करने के लिए कह सकते हैं।

यहां स्क्रिप्ट को संशोधित किया गया है ताकि jपृष्ठभूमि प्रक्रियाओं की संख्या का ट्रैक रखने के लिए उपयोग किया जा सके। जब NB_CONCURRENT_PROCESSESपहुंच जाता है, तो स्क्रिप्ट j0 पर रीसेट हो जाएगी और सभी पृष्ठभूमि प्रक्रियाओं के समाप्त होने से पहले इसे फिर से शुरू करने की प्रतीक्षा करें।

files=(./*.png)
nb_concurrent_processes=4
j=0
for f in "${files[@]}"
do
        echo "Processing $f file..."
        # take action on each file. $f store current file name
        ./pngout -s0 "$f" R"${f/\.\//}" &
        ((++j == nb_concurrent_processes)) && { j=0; wait; }
done

1
यह चार समवर्ती प्रक्रियाओं के अंतिम की प्रतीक्षा करेगा और फिर एक और चार का एक सेट शुरू करेगा। शायद एक को चार पीआईडी ​​की एक सरणी का निर्माण करना चाहिए और फिर इन विशिष्ट पीआईडी ​​के लिए इंतजार करना चाहिए?
निल्स

कोड को मेरे फ़िक्स को समझाने के लिए: (1) स्टाइल के मामले में, सभी अपरकेस वैरिएबल नामों से बचें क्योंकि वे आंतरिक शेल चर के साथ संभावित रूप से टकराव करते हैं। (2) $fआदि के लिए उद्धृत (3) [POSIX संगत स्क्रिप्ट के लिए उपयोग करें , लेकिन शुद्ध बैश के [[लिए हमेशा पसंद किया जाता है। इस मामले में, ((अंकगणित के लिए अधिक उपयुक्त है।
20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.