एक साथ कई समादेशों की सीमा के साथ समानांतर में कमांड चलाना


23

अनुक्रमिक: for i in {1..1000}; do do_something $i; done- बहुत धीमा

समानांतर: for i in {1..1000}; do do_something $i& done- बहुत अधिक भार

समानांतर में कमांड कैसे चलाएं, लेकिन इससे अधिक नहीं, उदाहरण के लिए, प्रति पल 20 उदाहरण?

अब आमतौर पर हैक की तरह उपयोग करते हैं for i in {1..1000}; do do_something $i& sleep 5; done, लेकिन यह एक अच्छा समाधान नहीं है।

अद्यतन 2 : स्वीकृत उत्तर को स्क्रिप्ट में परिवर्तित कर दिया: http://vi-server.org/vi/parallel

#!/bin/bash

NUM=$1; shift

if [ -z "$NUM" ]; then
    echo "Usage: parallel <number_of_tasks> command"
    echo "    Sets environment variable i from 1 to number_of_tasks"
    echo "    Defaults to 20 processes at a time, use like \"MAKEOPTS='-j5' parallel ...\" to override."
    echo "Example: parallel 100 'echo \$i; sleep \`echo \$RANDOM/6553 | bc -l\`'"
    exit 1
fi

export CMD="$@";

true ${MAKEOPTS:="-j20"}

cat << EOF | make -f - -s $MAKEOPTS
PHONY=jobs
jobs=\$(shell echo {1..$NUM})

all: \${jobs}

\${jobs}:
        i=\$@ sh -c "\$\$CMD"
EOF

ध्यान दें कि आपको इसे काम करने के लिए "i =" से पहले 8 स्थानों को 2 टैब से बदलना होगा।

जवाबों:


15

इसके लिए जीएनयू समानांतर बनाया गया है।

seq 1 1000 | parallel -j20 do_something

यह दूरस्थ कंप्यूटर पर भी नौकरी चला सकता है। प्रति सर्वर 2 और स्थानीय कंप्यूटर का उपयोग कर सीपीयू कोर में 1 काम करने वाले ओजीजी के लिए एमपी 3 को फिर से एन्कोडिंग के लिए एक उदाहरण दिया गया है:

parallel --trc {.}.ogg -j+0 -S server2,: \
     'mpg321 -w - {} | oggenc -q0 - -o {.}.ogg' ::: *.mp3

GNU समानांतर में एक परिचय वीडियो देखें:

http://www.youtube.com/watch?v=OpaiGYxkSuQ


"अधिक जानकारी" के बारे में नहीं जानते हैं और यह पहले से ही काम के लिए एक उपकरण है। देख रहे हैं और तुलना कर रहे हैं।
वि।

1
parallelMoreutils में जीएनयू समानांतर नहीं है और काफी इसके विकल्प में सीमित है। ऊपर की कमान अधिक्यूटाइल से समानांतर के साथ नहीं चलेगी।
ओले तांगे

1
एक और विकल्प xargs --max-procs=20:।
वि।

4

बैश समाधान नहीं है, लेकिन आपको मेकफाइल का उपयोग करना चाहिए, संभवतः -lकुछ अधिकतम भार से अधिक नहीं।

NJOBS=1000

.PHONY = jobs
jobs = $(shell echo {1..$(NJOBS)})

all: $(jobs)

$(jobs):
    do_something $@

फिर एक बार में 20 काम शुरू करने के लिए

$ make -j20

या 5 के भार से अधिक के बिना जितना संभव हो उतने काम शुरू करने के लिए

$ make -j -l5

अब के लिए गैर-हैकी समाधान की तरह दिखता है।
वि।

2
echo -e 'PHONY=jobs\njobs=$(shell echo {1..100000})\n\nall: ${jobs}\n\n${jobs}:\n\t\techo $@; sleep `echo $$RANDOM/6553 | bc -l`' | make -f - -j20अब यह फिर से ज्यादा हैकी लग रहा है।
वि।


अपने समाधान को स्क्रिप्ट में परिवर्तित कर दिया। अब इसे आसानी के साथ इस्तेमाल किया जा सकता है।
वि।

2

प्रारूपण के साथ प्रश्न में स्क्रिप्ट पोस्ट करना:

#!/bin/bash

NUM=$1; shift

if [ -z "$NUM" ]; then
    echo "Usage: parallel <number_of_tasks> command"
    echo "    Sets environment variable i from 1 to number_of_tasks"
    echo "    Defaults to 20 processes at a time, use like \"MAKEOPTS='-j5' parallel ...\" to override."
    echo "Example: parallel 100 'echo \$i; sleep \`echo \$RANDOM/6553 | bc -l\`'"
    exit 1
fi

export CMD="$@";

true ${MAKEOPTS:="-j20"}

cat << EOF | make -f - -s $MAKEOPTS
PHONY=jobs
jobs=\$(shell echo {1..$NUM})

all: \${jobs}

\${jobs}:
        i=\$@ sh -c "\$\$CMD"
EOF

ध्यान दें कि आपको "i =" से पहले 8 स्थानों को 2 टैब से बदलना होगा।


1

एक सरल विचार:

I modulo 20 की जाँच करें और do_something से पहले प्रतीक्षा शेल-कमांड निष्पादित करें।


यह या तो सभी वर्तमान कार्यों को पूरा करने के लिए इंतजार करेगा (कार्यों की संख्या में भूखंडों को बना रहा है) या एक विशिष्ट कार्य की प्रतीक्षा करें जो अधिक समय तक रुक सकता है (इस मामले में फिर से sags बनाना)
Vi।

@ वी: शेल प्रतीक्षा सभी पृष्ठभूमि कार्यों के लिए है जो इस शेल से संबंधित हैं।

1

आप यह psगिनने के लिए उपयोग कर सकते हैं कि आपके पास कितनी प्रक्रियाएँ चल रही हैं, और जब भी यह एक निश्चित सीमा से नीचे चली जाती है तो आप एक और प्रक्रिया शुरू करते हैं।

छद्म कोड:

i = 1
MAX_PROCESSES=20
NUM_TASKS=1000
do
  get num_processes using ps
  if num_processes < MAX_PROCESSES
    start process $i
    $i = $i + 1
  endif
  sleep 1 # add this to prevent thrashing with ps
until $i > NUM_TASKS

1
for i in {1..1000}; do 
     (echo $i ; sleep `expr $RANDOM % 5` ) &
     while [ `jobs | wc -l` -ge 20 ] ; do 
         sleep 1 
     done
done

हो सकता है while [ `jobs | wc -l` -ge 20]; do?
वि।

यकीन है, लेकिन मेरे नमूने में, मुझे फिर njobsदो बार गणना करनी होगी , और प्रदर्शन शेल स्क्रिप्ट में काफी महत्वपूर्ण है जो नींद कार्यों को चलाता है;)
msw

मेरा मतलब है कि आपका संस्करण अपेक्षा के अनुरूप काम नहीं करता है। मैं बदल sleep 1जाता हूं sleep 0.1और यह 20 के बजाय 40-50 के औसत औसत करने के लिए शुरू होता है। अगर 20 से अधिक नौकरियां हैं, तो हमें किसी भी नौकरी के लिए इंतजार करने की आवश्यकता है, केवल 1 सेकंड इंतजार न करें।
वि।

0

आप इसे इस तरह से कर सकते हैं।

threads=20
tempfifo=$PMS_HOME/$$.fifo

trap "exec 1000>&-;exec 1000<&-;exit 0" 2
mkfifo $tempfifo
exec 1000<>$tempfifo
rm -rf $tempfifo

for ((i=1; i<=$threads; i++))
do
    echo >&1000
done

for ((j=1; j<=1000; j++))
do
    read -u1000
    {
        echo $j
        echo >&1000
    } &
done

wait
echo "done!!!!!!!!!!"

हर बार नामित पाइप का उपयोग करते हुए, यह समानांतर में 20 उप शेल चलाता है।

आशा है कि यह मदद :)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.