2012-06-18 76 views
10

Tôi đang viết một kịch bản trong trình bao trong đó một lệnh đang chạy và dùng 2 phút. mỗi lần. Ngoài ra, chúng tôi không thể làm gì với điều này. Nhưng nếu tôi muốn chạy lệnh này 100 lần trong kịch bản thì tổng thời gian sẽ là 200 phút. và điều này sẽ tạo ra một vấn đề lớn. Không ai muốn chờ khoảng 200 phút. Những gì tôi muốn là chạy tất cả 100 lệnh song song để đầu ra sẽ đến trong 2 phút hoặc có thể là một số thời gian hơn nhưng không mất 200 phút.Xử lý song song hoặc luồng trong Shell scripting

nó sẽ được đánh giá cao, nếu bất kỳ cơ thể có thể giúp tôi về điều này trong bất kỳ cách nào.

+0

[Bạn đã thử gì] (http://mattgemmell.com/2008/12/08/what-have-you-tried/)? – ghoti

+0

Ngoài ra, bạn đang sử dụng trình bao nào? tcsh? zsh? pd-ksh? cá? – Graham

Trả lời

10

... chạy tất cả 100 lệnh song song nên đầu ra sẽ có 2min

này chỉ có thể nếu bạn có 200 bộ xử lý trên hệ thống của bạn.

Không có tiện ích/lệnh như vậy trong kịch bản lệnh shell để chạy các lệnh song song. Những gì bạn có thể làm là chạy lệnh của bạn ở chế độ nền:

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

Với & (nền), từng thực hiện được lên kế hoạch càng sớm càng tốt. Nhưng điều này không đảm bảo rằng mã của bạn sẽ được thực hiện trong ít hơn 200 phút. Nó phụ thuộc vào việc có bao nhiêu bộ vi xử lý trên hệ thống của bạn.

Nếu bạn chỉ có một bộ xử lý và mỗi lần thực thi lệnh (mất 2 phút) sẽ thực hiện tính toán trong 2 phút, thì bộ xử lý sẽ thực hiện một số công việc, nghĩa là không có chu kỳ bị lãng phí. Trong trường hợp này, chạy các lệnh song song sẽ không được trợ giúp bởi vì, chỉ có một bộ xử lý cũng không phải là miễn phí. Vì vậy, các quá trình sẽ chỉ chờ đợi đến lượt của họ được thực hiện.

Nếu bạn có nhiều bộ xử lý, thì phương pháp trên (đối với vòng lặp) có thể giúp giảm tổng thời gian thực hiện.

+1

Nếu kịch bản là IO bị ràng buộc, bạn không cần 200 bộ vi xử lý. Trong thực tế, một tốc độ đáng kể có thể đạt được chỉ với 1 bộ vi xử lý. –

+0

@WilliamPursell Đúng vậy. Nhưng nó thực sự phụ thuộc vào những gì lệnh đang làm cho điều đó * 2 phút *. –

4

Như @KingsIndian đã nói, bạn có thể thực hiện các tác vụ nền, cho phép chúng chạy song song. Ngoài ra, bạn cũng có thể theo dõi chúng theo ID quá trình:

#!/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))" 

Bạn cũng nên xem tài liệu Bash trên coprocesses.

13

GNU Parallel là những gì bạn muốn, trừ khi bạn muốn phát minh lại bánh xe. Dưới đây là một số chi tiết cụ thể hơn examples, nhưng ngắn gọn:

ls | parallel gzip # gzip all files in a directory 
Các vấn đề liên quan