Thực hiện song song một chương trình trên nhiều tệp


7

Tôi có một đoạn script nhỏ lặp qua tất cả các tệp của một thư mục và thực thi lệnh (thường là kéo dài). Về cơ bản là

for file in ./folder/*;
do
    ./bin/myProgram $file > ./done/$file
done

(Vui lòng bỏ qua lỗi cú pháp, đó chỉ là mã giả).

Bây giờ tôi muốn chạy kịch bản này hai lần cùng một lúc. Rõ ràng, việc thực thi là không cần thiết nếu ./done/$file tồn tại. Vì vậy, tôi đã thay đổi kịch bản thành

for file in ./folder/*;
do
    [ -f ./done/$file ] || ./bin/myProgram $file >./done/$file
done

Vì vậy, về cơ bản câu hỏi là: Có thể cả hai tập lệnh (hoặc nói chung nhiều hơn một tập lệnh) thực sự ở cùng một điểm và kiểm tra sự tồn tại của donetập tin bị lỗi và lệnh chạy hai lần?

nó sẽ là hoàn hảo, nhưng tôi rất nghi ngờ nó Điều này sẽ quá dễ dàng: D Nếu có thể xảy ra việc họ xử lý cùng một tệp, thì bằng cách nào đó có thể "đồng bộ hóa" các tập lệnh không?


Nếu bạn có một phiên bản xargsvới -Ptùy chọn có sẵn, hãy xem câu hỏi này .
jw013

2
GNU Make cũng hỗ trợ thực thi song song; các done/$fileđiểm đánh dấu có vẻ hơi giống makemục tiêu đối với tôi.
sr_

2
Mã (giả) mà bạn đã đăng không thực sự chạy song song hai phiên bản chương trình của bạn. Nếu bạn có xargshoặc GNU makehoặc một số phiên bản của parallel, thì không cần phải phát minh lại bánh xe cụ thể này.
jw013

Nó sẽ chạy hai trường hợp nếu đoạn script trên được thực thi hai lần
stefan

Câu trả lời:


4

Điều này là có thể và xảy ra trong thực tế. Sử dụng một tập tin khóa để tránh tình trạng này. Một ví dụ, từ trang đã nói:

if mkdir /var/lock/mylock; then
    echo "Locking succeeded" >&2
else
    echo "Lock failed - exit" >&2
    exit 1
fi

# ... program code ...

rmdir /var/lock/mylock

1
"Là một bên, bạn gần như chắc chắn muốn trích dẫn tập tin $." Điều đó không cần thiết cho công việc đơn giản của tôi, nhưng rõ ràng là quyền của bạn, rằng sẽ tốt hơn nếu làm như vậy
stefan

@stefan - Tôi đã xóa nó khi tôi thấy "bỏ qua lỗi cú pháp" ... :-)
Chris Down

: D nó hoàn toàn ổn nếu bạn nhắc tôi về những thứ này. Tôi có xu hướng quên nó đi vì tôi chưa quen với nó
stefan

Tôi hoàn toàn YÊU sự đơn giản của khóa mkdir. Cảm ơn các liên kết! (mặc dù tôi sẽ thích nó đọc về nó trên trang web này, có lẽ bạn muốn mở rộng câu trả lời của mình một chút?)
stefan

2

Hai phiên bản của tập lệnh của bạn chắc chắn có thể tương tác theo cách này, khiến lệnh chạy hai lần. Điều này được gọi là một điều kiện chủng tộc .

Một cách để tránh điều kiện cuộc đua này là nếu mỗi trường hợp lấy tệp đầu vào của nó bằng cách di chuyển nó sang thư mục khác. Di chuyển một tập tin (bên trong cùng một hệ thống tập tin) là nguyên tử . Di chuyển các tập tin đầu vào có thể không được mong muốn, và điều này đã trở nên hơi phức tạp.

mkdir staging-$$ making-$$
for input in folder/*; do
  name=${x#folder/}
  staging=staging-$$/$name
  output=making-$$/$name
  destination=done/$name
  if mv -- "$input" "$staging" 2>/dev/null; then
    bin/myProgram "$staging" >"$output"
    mv -- "$output" "$destination"
    mv -- "$staging" "$input"
  fi
done

Một cách đơn giản để xử lý các tệp song song bằng cách sử dụng một công cụ có sẵn rộng rãi là GNU make , sử dụng -jcờ để thực thi song song . Đây là một tệp thực hiện cho tác vụ này (hãy nhớ sử dụng các tab để thụt lề các lệnh):

all: $(patsubst folder/%,done/%,$(wildcard folder/*))
done/%: folder/%
        ./bin/myProgram $< >$@.tmp
        mv $@.tmp $@

Chạy make -j 3để chạy song song 3 trường hợp.

Xem thêm Bốn nhiệm vụ song song ... làm thế nào để tôi làm điều đó?


Cảm ơn bạn rất nhiều vì câu trả lời này. Nếu tôi có thể chấp nhận hai câu trả lời, tôi sẽ!
stefan

1

Tôi có cảm giác bạn đang thực sự cố gắng chạy song song nhiều công việc và tệp khóa chỉ đơn giản là một phương tiện để kết thúc.

Nếu bạn đã cài đặt GNU Parallel http://www.gnu.org/software/pool/, bạn có thể làm điều này:

parallel ./bin/myProgram ::: ./folder/*

Nó sẽ chạy myProgram trên mỗi lõi song song.

Bạn có thể cài đặt GNU Parallel đơn giản bằng cách:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Xem các video giới thiệu về GNU Parallel để tìm hiểu thêm: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


0

Vấn đề với khóa là bạn cần một phương pháp tạo ra khóa không bị gián đoạn (đôi khi được gọi là nguyên tử). Như Chris đã viết trong câu trả lời của mình mkdirlà một hoạt động không thể gián đoạn (tạo một tệp không phải là hoạt động như vậy).

Ngoài ra còn có một lệnh cấp cao - ẩn trong procmailgói : lockfile. Lệnh đó có một số tính năng hay và có thể dễ dàng được sử dụng trong các tập lệnh của riêng bạn mà không cần phải "phát minh lại bánh xe" (ví dụ, viết chức năng của riêng bạn mà khóa dựa trên việc tạo thư mục).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.