2012-06-18 29 views
10

Piszę skrypt w powłoce, w którym polecenie jest uruchomione i trwa 2 min. każdego razu. Poza tym nic nie możemy z tym zrobić. Ale jeśli chcę uruchomić to polecenie 100 razy w skrypcie, całkowity czas to 200 minut. a to stworzy duży problem. Nikt nie chce czekać na 200min. To, czego chcę, to równoległe uruchamianie wszystkich 100 poleceń, tak aby dane wyjściowe przychodziły w ciągu 2 minut lub może trochę więcej czasu, ale nie trwało to 200 minut.Równoległe przetwarzanie lub wątkowanie w skrypcie powłoki

będzie to docenione, jeśli jakakolwiek instytucja może mi w tym pomóc w jakikolwiek sposób.

+0

[Co próbowałeś] (http://mattgemmell.com/2008/12/08/what-have-you-tried/)? – ghoti

+0

Jakiej powłoki używasz? tcsh? zsh? pd-ksh? ryba? – Graham

Odpowiedz

10

... uruchomić wszystkie polecenia 100 równolegle tak, że produkcja wejdzie w 2min

Jest to możliwe tylko wtedy, gdy masz 200 procesorów w systemie.

Nie ma takiego narzędzia/polecenia w skrypcie powłoki, aby uruchamiać polecenia równolegle. Co można zrobić, to uruchomić polecenie w tle:

for ((i=0;i<200;i++)) 
do 
    MyCommand & 
done 

Z & (tło), każde wykonanie jest zaplanowane tak szybko, jak to możliwe. Ale to nie gwarantuje, że twój kod zostanie wykonany w mniej niż 200 minut. Zależy to od liczby procesorów w twoim systemie.

Jeśli masz tylko jeden procesor, a każde wykonanie polecenia (trwa to 2 minuty), wykonuje pewne obliczenia przez 2 minuty, a następnie procesor wykonuje pewne czynności, co oznacza, że ​​nie ma niepotrzebnych cykli. W tym przypadku równoległe uruchamianie poleceń nie pomoże, ponieważ istnieje tylko jeden procesor, który również nie jest wolny. Tak więc procesy będą po prostu czekać na wykonanie swojej kolejki.

Jeśli masz więcej niż jeden procesor, powyższa metoda (dla pętli) może pomóc w skróceniu całkowitego czasu wykonania.

+1

Jeśli skrypt jest powiązany z IO, nie potrzebujesz 200 procesorów. W rzeczywistości można uzyskać znaczne przyspieszenie przy użyciu tylko jednego procesora. –

+0

@WilliamPursell To prawda. Ale to naprawdę zależy od tego, co polecenie robi w tym * 2 minuty *. –

4

Jak powiedział @KingsIndian, można wykonywać zadania w tle, które pozwalają im pracować równolegle. Poza tym, można również śledzić ich przez ID procesu:

#!/bin/bash 

# Function to be backgrounded 
track() { 
    sleep $1 
    printf "\nFinished: %d\n" "$1" 
} 

start=$(date '+%s') 

rand3="$(jot -s\ -r 3 5 10)" 

# If you don't have `jot` (*BSD/OSX), substitute your own numbers here. 
#rand3="5 8 10" 

echo "Random numbers: $rand3" 

# Make an associative array in which you'll record pids. 
declare -A pids 

# Background an instance of the track() function for each number, record the pid. 
for n in $rand3; do 
    track $n & 
    pid=$! 
    echo "Backgrounded: $n (pid=$pid)" 
    pids[$pid]=$n 
done 

# Watch your stable of backgrounded processes. 
# If a pid goes away, remove it from the array. 
while [ -n "${pids[*]}" ]; do 
    sleep 1 
    for pid in "${!pids[@]}"; do 
    if ! ps "$pid" >/dev/null; then 
     unset pids[$pid] 
     echo "unset: $pid" 
    fi 
    done 
    if [ -z "${!pids[*]}" ]; then 
    break 
    fi 
    printf "\rStill waiting for: %s ... " "${pids[*]}" 
done 

printf "\r%-25s \n" "Done." 
printf "Total runtime: %d seconds\n" "$((`date '+%s'` - $start))" 

Należy również przyjrzeć się dokumentacji Bash coprocesses.

13

GNU Parallel jest to, czego chcesz, chyba że chcesz odkryć nowe koło. Oto kilka szczegółowych examples, ale brakuje go:

ls | parallel gzip # gzip all files in a directory 
Powiązane problemy