समानांतर में निष्पादित पाइप कमांड


16

निम्नलिखित परिदृश्य पर विचार करें। मेरे पास दो प्रोग्राम ए और बी हैं। प्रोग्राम ए आउटपुट के स्ट्रैंडआउट लाइन को आउटपुट करता है, जबकि प्रोग्राम बी प्रक्रिया लाइनों को स्टडिन से। इन दो कार्यक्रमों का उपयोग करने का तरीका निश्चित रूप से है:

foo @ बार: ~ $ A | बी

अब मैंने देखा कि यह केवल एक कोर खाता है; इसलिए मैं सोच रहा हूँ:

क्या प्रोग्राम A और B समान कम्प्यूटेशनल संसाधनों को साझा कर रहे हैं? यदि हां, तो क्या ए और बी को समवर्ती तरीके से चलाने का कोई तरीका है?

एक और बात जिस पर मैंने गौर किया है कि A, B की तुलना में बहुत तेज दौड़ता है, इसलिए मैं सोच रहा हूं कि क्या किसी तरह से अधिक B प्रोग्राम चलाए जा सकते हैं और उन्हें उन लाइनों को संसाधित करने दें जो समानांतर में A आउटपुट करती हैं।

यही है, ए अपनी लाइनों का उत्पादन करेगा, और प्रोग्राम बी के एन उदाहरण होंगे जो इन पंक्तियों को पढ़ेंगे (जो भी उन्हें पहले पढ़ते हैं) उन्हें संसाधित करते हैं और उन्हें स्टडआउट पर आउटपुट करते हैं।

तो मेरा अंतिम प्रश्न है:

क्या रेस की स्थिति और संभावित रूप से उत्पन्न होने वाली अन्य विसंगतियों की देखभाल के बिना कई बी प्रक्रियाओं के बीच ए से आउटपुट को पाइप करने का एक तरीका है?


1
जबकि A | B | Cअलग-अलग प्रक्रियाओं में समानांतर है, पाइप की प्रकृति के कारण (बी को ए के आउटपुट के लिए इंतजार करना पड़ता है, सी को बी के उत्पादन के लिए इंतजार करना पड़ता है) यह अभी भी कुछ मामलों में रैखिक हो सकता है। यह पूरी तरह से इस बात पर निर्भर करता है कि वे किस तरह का उत्पादन करते हैं। ऐसे कई मामले नहीं हैं, जहां एकाधिक भाग लेने Bसे बहुत मदद मिलेगी, यह पूरी तरह से संभव है कि समानांतर wc उदाहरण नियमित wcरूप से धीमा हो क्योंकि विभाजन के कारण सामान्य रूप से लाइनों की गिनती की तुलना में अधिक संसाधन हो सकते हैं। देखभाल के साथ उपयोग करें।
ठंढकुट्ज़

जवाबों:


14

इसके साथ एक समस्या split --filterयह है कि आउटपुट को मिलाया जा सकता है, इसलिए आपको प्रक्रिया 1 से आधी रेखा मिलती है और इसके बाद प्रक्रिया 2 से आधी रेखा मिलती है।

GNU पैरेलल गारंटी में कोई भी मिलावट नहीं होगी।

इसलिए मान लें कि आप क्या करना चाहते हैं:

 A | B | C

लेकिन वह B बहुत धीमा है, और इस प्रकार आप उसे समानांतर करना चाहते हैं। तो आप कर सकते हैं:

A | parallel --pipe B | C

डिफ़ॉल्ट रूप से GNU समानांतर \ n पर विभाजित होता है और 1 MB का ब्लॉक आकार होता है। इसे --recend और --block के साथ समायोजित किया जा सकता है।

आप GNU के बारे में और अधिक जानकारी प्राप्त कर सकते हैं: http://www.gnu.org/s/parallel/

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

wget -O - pi.dk/3 | sh 

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


1
हालांकि मैं इंस्टॉलेशन पद्धति :-), +1 पर पूरी तरह असहमत हूं क्योंकि आपका समाधान मेरी अधिकांश समस्याओं को हल करता है।
एलसर्नी

यह वास्तव में अच्छा है। क्या आपके पास उपयोग किए जाने वाले मापदंडों के लिए भी कोई सुझाव है? मुझे पता है कि प्रोग्राम ए 1 टीबी से अधिक डेटा लगभग 5 जीबी प्रति मिनट का उत्पादन करेगा। प्रोग्राम B, ए आउटपुट से 5 गुना धीमा डेटा संसाधित करता है और इस कार्य के लिए मेरे निपटान में 5 कोर हैं।
जर्नजीज

जीएनयू समानांतर वर्तमान में 100 एमबी / एस के आसपास सबसे अधिक संभाल सकता है, इसलिए आप उस सीमा को छूने जा रहे हैं। इष्टतम --block-sizeरैम की मात्रा पर निर्भर करेगा और आप कितनी तेजी से एक नई शुरुआत कर सकते हैं B। आपकी स्थिति में मैं उपयोग करता हूं --block 100Mऔर देखता हूं कि कैसे प्रदर्शन किया।
ओले तांगे

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

4
क्षमा करें, मैंने खुद को स्पष्ट नहीं किया। संस्थापन विधि - स्क्रिप्ट को पास किया गया sh- महान है। समस्या इसे पास करने में निहित है: एक साइट से निष्पादन योग्य कोड को डाउनलोड करना और चलाना । ध्यान रहे, हो सकता है कि मैं अभी बहुत ज्यादा पागल हो रहा हूं, क्योंकि कोई आपत्ति कर सकता है कि एक कस्टम-निर्मित RPM या DEB मूल रूप से एक ही बात है, और यहां तक ​​कि कॉपी किए गए और चिपकाए जाने वाले पृष्ठ पर कोड को पोस्ट करने से लोगों को आंख मूंदकर ऐसा करना होगा वैसे भी।
LSerni

13

जब आप लिखते हैं A | B, तो दोनों प्रक्रियाएं पहले से ही समानांतर में चलती हैं। यदि आप उन्हें केवल एक कोर का उपयोग करते हुए देखते हैं, तो शायद इसलिए कि सीपीयू आत्मीयता सेटिंग्स में से किसी एक (शायद अलग-अलग आत्मीयता के साथ एक प्रक्रिया को स्पॉन करने के लिए कुछ उपकरण है) या क्योंकि एक प्रक्रिया पूरे कोर को धारण करने के लिए पर्याप्त नहीं है, और सिस्टम " पसंद "कंप्यूटिंग को फैलाने के लिए नहीं।

कई बी को एक ए के साथ चलाने के लिए, आपको एक उपकरण की आवश्यकता है जैसे splitकि --filterविकल्प के साथ :

A | split [OPTIONS] --filter="B"

यह, हालांकि, आउटपुट में लाइनों के क्रम को गड़बड़ाने के लिए उत्तरदायी है, क्योंकि बी नौकरियां सभी एक ही गति से नहीं चल रही होंगी। यदि यह एक समस्या है, तो आपको एक इंटरमीडिएट फ़ाइल में B i-th आउटपुट को रीडायरेक्ट करने और अंत में उन्हें एक साथ उपयोग करने की आवश्यकता हो सकती है cat। यह, बदले में, एक काफी डिस्क स्थान की आवश्यकता हो सकती है।

अन्य विकल्प मौजूद हैं (उदाहरण के लिए आप एक ही लाइन बफ़र उत्पादन के लिए बी के प्रत्येक उदाहरण के सीमित हो सकती है, जब तक इंतजार एक पूरी बी के के "दौर" समाप्त हो गया है, एक के बराबर चलाने को कम करने के लिए splitकी नक्शा , और catअस्थायी उत्पादन एक साथ), दक्षता के विभिन्न स्तरों के साथ। उदाहरण के लिए वर्णित 'राउंड' विकल्प B के सबसे धीमे उदाहरण के लिए प्रतीक्षा करेगा , इसलिए यह B के लिए उपलब्ध बफरिंग पर बहुत निर्भर करेगा; [m]bufferऑपरेशन क्या हैं, इस पर निर्भर करते हुए, यह मदद कर सकता है या नहीं।

उदाहरण

पहले 1000 नंबर जेनरेट करें और लाइनों को समानांतर में गिनें:

seq 1 1000 | split -n r/10 -u --filter="wc -l"
100
100
100
100
100
100
100
100
100
100

यदि हम लाइनों को "चिह्नित" करने के लिए थे, तो हम देखेंगे कि प्रत्येक पहली पंक्ति को # 1, प्रत्येक पांचवीं पंक्ति को # 5 और इसी तरह संसाधित करने के लिए भेजा जाता है। इसके अलावा, splitदूसरी प्रक्रिया को शुरू करने में लगने वाले समय में , पहले से ही कोटा में एक अच्छा तरीका है:

seq 1 1000 | split -n r/10 -u --filter="sed -e 's/^/$RANDOM - /g'" | head -n 10
19190 - 1
19190 - 11
19190 - 21
19190 - 31
19190 - 41
19190 - 51
19190 - 61
19190 - 71
19190 - 81

जब 2-कोर मशीन पर निष्पादित किया जाता है seq, splitऔर wcप्रक्रियाएं कोर साझा करती हैं; लेकिन करीब देखते हुए, सिस्टम CPU0 पर पहले दो प्रक्रियाओं को छोड़ देता है, और CPU1 को कार्यकर्ता प्रक्रियाओं में विभाजित करता है:

%Cpu0  : 47.2 us, 13.7 sy,  0.0 ni, 38.1 id,  1.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  : 15.8 us, 82.9 sy,  0.0 ni,  1.0 id,  0.0 wa,  0.3 hi,  0.0 si,  0.0 st
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM     TIME+ COMMAND
 5314 lserni    20   0  4516  568  476 R 23.9  0.0   0:03.30 seq
 5315 lserni    20   0  4580  720  608 R 52.5  0.0   0:07.32 split
 5317 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.86 wc
 5318 lserni    20   0  4520  572  484 S 14.0  0.0   0:01.88 wc
 5319 lserni    20   0  4520  576  484 S 13.6  0.0   0:01.88 wc
 5320 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.85 wc
 5321 lserni    20   0  4520  572  484 S 13.3  0.0   0:01.84 wc
 5322 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.86 wc
 5323 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.86 wc
 5324 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.87 wc

विशेष रूप से ध्यान दें कि splitसीपीयू काफी मात्रा में खा रहा है। यह ए की जरूरतों के अनुपात में कमी आएगी; यानी, यदि A की तुलना में भारी प्रक्रिया है seq, तो सापेक्ष उपरि splitघट जाएगी। लेकिन अगर एक एक बहुत ही हल्के प्रक्रिया है और बी काफी तेज है (ताकि आप कोई जरूरत से ज्यादा 2-3 बी के एक साथ रखने के लिए), तो साथ parallelizing split(या सामान्य रूप में पाइप) हो सकता है अच्छी तरह से इसके लायक नहीं हो।


दिलचस्प है कि उबंटू पर पाए गए विभाजन में --filter विकल्प नहीं है। इसके लिए ओएस किस तरह का उपयोग कर रहे हैं?
जर्नजीज

Linux OpenSuSE 12.3, कोरुटिल्स के साथ ( gnu.org/software/coreutils/manual/html_node/… )। मैं कोशिश करूँगा और एक उबंटू को पकड़ लूंगा, हो सकता है कि उन्होंने कुछ समान नाम वाले टूल को समायोजित करने के लिए नाम बदल दिया हो।
LSerni

क्या आप split --filterविकल्प गायब हैं? मेरे Ubuntu 12.04-LTS ("wheezy / sid") पर, यह वहां है, और मेरे उदाहरण काम करते हैं। क्या आप splitग्नू कोरुटिल्स में एक से अधिक को स्थापित कर सकते हैं ?
एलसर्नी

इसके लिए धन्यवाद। मुझे Coreutils का एक नया संस्करण स्थापित करना था। BTW, मैंने देखा है कि अगर मैं प्रोग्राम A को चलाता हूं तो यह A को चलाने पर एक संपूर्ण कोर (100%) खाता है B तब वे एक साथ एक संपूर्ण कोर खाते हैं, A A 15% खाने की प्रक्रिया करते हैं और B 85% खाने की प्रक्रिया करते हैं .. क्या आप देखते हैं कि ऐसा क्यों है?
जर्नजीज

2
अवरुद्ध होने के कारण यह संभावना है । यदि B A से अधिक भारी है, तो A अपना आउटपुट नहीं भेज सकता है और धीमा हो जाता है। एक और संभावना ए ऑपरेशन के दौरान बी की उपज है (जैसे डिस्क / नेट)। एक अलग सिस्टम पर, आप B gbbling को CPU 1 का 100% और A को 18% CPU0 सौंपा जा सकता है। शायद आपको सिंगल कोर को संतृप्त करने के लिए एक ए उदाहरण प्राप्त करने के लिए बी के 5 और 6 उदाहरणों के बीच 85/15 ~ 5.67 = की आवश्यकता है। मैं / ओ, यदि मौजूद है, तो इन मूल्यों को तिरछा कर सकता है, हालांकि।
एलसर्नी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.