मैंने इस विषय के बारे में इसी तरह के प्रश्न पढ़े हैं, लेकिन उनमें से कोई भी मुझे निम्न समस्या में मदद नहीं करता है:

मेरे पास एक बैश स्क्रिप्ट है जो इस तरह दिखती है:

#!/bin/bash

for filename  in /home/user/Desktop/emak/*.fa; do
    mkdir ${filename%.*}
    cd ${filename%.*}
    mkdir emak
    cd ..
done

यह लिपि मूल रूप से निम्नलिखित कार्य करती है:

  • एक निर्देशिका में सभी फ़ाइलों के माध्यम से बदल
  • प्रत्येक फ़ाइल के नाम के साथ एक नई निर्देशिका बनाएं
  • नई फ़ाइल के अंदर जाएं और "emak" नामक एक नई फ़ाइल बनाएं

वास्तविक कार्य "emak" फ़ाइल बनाने की तुलना में कुछ अधिक महंगा है ...

मैं के माध्यम से iterate करने के लिए हजारों फ़ाइलों के बारे में है। जैसा कि प्रत्येक पुनरावृत्ति पिछले एक से स्वतंत्र है, मैं इसे अलग-अलग प्रोसेसर में विभाजित करना पसंद करूंगा (मेरे पास 24 कोर हैं) इसलिए मैं एक ही समय में फ़ाइलों को कई गुना कर सकता हूं।

मैंने समानांतर में चलने के बारे में कुछ पिछली पोस्ट पढ़ी (उपयोग करते हुए: जीएनयू) लेकिन मुझे इस मामले में इसे लागू करने का एक स्पष्ट तरीका नहीं दिख रहा है।

धन्यवाद

3
aspire57 24 नवम्बर 2015, 17:59

2 जवाब

सबसे बढ़िया उत्तर

GNU पैरेलल के साथ कुछ इस तरह से, जिससे आप doit नामक एक बैश फंक्शन बनाते और निर्यात करते हैं:

#!/bin/bash

doit() {
    dir=${1%.*}
    mkdir "$dir"
    cd "$dir"
    mkdir emak
}
export -f doit
parallel doit ::: /home/user/Desktop/emak/*.fa

यदि आपके "कम्प्यूटेशनल रूप से महंगा" भाग लंबा है, या विशेष रूप से चर द्वारा लिया गया समय है, तो आप वास्तव में इस दृष्टिकोण का लाभ देखेंगे। यदि यह लेता है, 10 सेकंड तक कहता है और परिवर्तनशील है, तो जीएनयू समानांतर एन जॉब्स के अगले बैच को शुरू करने से पहले सभी एन के पूरा होने की प्रतीक्षा करने के बजाय, एन समानांतर प्रक्रियाओं की सबसे छोटी प्रक्रिया पूरी होते ही अगली नौकरी प्रस्तुत करेगा।

कच्चे बेंचमार्क के रूप में, यह 58 सेकंड लेता है:

#!/bin/bash

doit() {
   echo $1
   # Sleep up to 10 seconds
   sleep $((RANDOM*11/32768))
}
export -f doit
parallel -j 10 doit ::: {0..99}

और यह सीधे तुलनीय है और इसमें 87 सेकंड लगते हैं:

#!/bin/bash
N=10
for i in {0..99}; do
    echo $i
    sleep $((RANDOM*11/32768)) &
    (( ++count % N == 0)) && wait
done
2
Mark Setchell 24 नवम्बर 2015, 17:43

parallel की कोई आवश्यकता नहीं; आप बस उपयोग कर सकते हैं

N=10
for filename in /home/user/Desktop/emak/*.fa; do
    mkdir -p "${filename%.*}/emak" &
    (( ++count % N == 0)) && wait
done

दूसरी पंक्ति हर Nth नौकरी को रोकती है ताकि पहले की सभी नौकरियों को जारी रखने से पहले पूरा किया जा सके।

3
chepner 24 नवम्बर 2015, 17:19