Chạy các chương trình song song bằng xargs


85

Tôi hiện có kịch bản hiện tại.

#!/bin/bash
# script.sh

for i in {0..99}; do
   script-to-run.sh input/ output/ $i
done

Tôi muốn chạy nó song song bằng cách sử dụng xargs. Tôi đã thử

script.sh | xargs -P8

Nhưng làm như trên chỉ thực hiện một lần vào thời điểm đó. Không may mắn với -n8 là tốt. Thêm & vào cuối dòng được thực thi trong vòng lặp script for sẽ cố gắng chạy script 99 lần cùng một lúc. Làm cách nào để tôi thực hiện vòng lặp chỉ 8 tại thời điểm đó, tổng cộng tối đa 100.


Đó là những gì ban đầu tôi muốn làm, nhưng phải dùng đến xargs vì tôi đang sử dụng Windows. Tôi không thể chạy GNU Song song trên Windows
Olivier

Tập lệnh đó tự gọi hay bạn chỉ nhầm lẫn giữa các tên khi hỏi ở đây?
Etan Reisner

Xin lỗi, nó nên gọi một tập lệnh khác. Tôi sẽ sửa nó
Olivier

Câu trả lời cho stackoverflow.com/questions/3321738/… có liên quan ở đây.
Etan Reisner

Câu trả lời:


128

Từ xargstrang người đàn ông:

Trang hướng dẫn này ghi lại phiên bản GNU của xargs. xargs đọc các mục từ đầu vào tiêu chuẩn, được phân cách bằng khoảng trống (có thể được bảo vệ bằng dấu ngoặc kép hoặc đơn hoặc dấu gạch chéo ngược) hoặc dòng mới và thực hiện lệnh (mặc định là / bin / echo) một hoặc nhiều lần với bất kỳ đối số ban đầu nào được theo sau bởi các mục được đọc từ đầu vào tiêu chuẩn. Các dòng trống trên đầu vào chuẩn bị bỏ qua.

Điều đó có nghĩa là ví dụ của bạn xargsđang đợi và thu thập tất cả đầu ra từ tập lệnh của bạn rồi chạy echo <that output>. Không chính xác tất cả những gì hữu ích cũng như những gì bạn muốn.

Đối -nsố là có bao nhiêu mục từ đầu vào để sử dụng với mỗi lệnh được chạy (không có gì, tự nó, về tính song song ở đây).

Để làm những gì bạn muốn với xargsbạn, bạn sẽ cần phải làm thêm một số việc như sau (chưa được kiểm tra):

printf %s\\n {0..99} | xargs -n 1 -P 8 script-to-run.sh input/ output/

Mà hỏng hóc thế này.

  • printf %s\\n {0..99}- In một số trên mỗi dòng từ 0đến 99.
  • Chạy xargs
    • lấy nhiều nhất một đối số trên mỗi dòng lệnh chạy
    • và chạy tối đa tám quy trình cùng một lúc

7
Trên thực tế, bạn không cần phải đặt các đối số trên các dòng riêng biệt; xargs tách từ. Vì vậy, echo {0..99} |sẽ hoạt động tốt. <<<{0..99}dường như không hoạt động; mặc dù <<<wordđược ghi nhận là từ mở rộng dấu ngoặc nhọn, nhưng nó không làm như vậy với bất kỳ phiên bản bash nào mà tôi có.
rici

1
@rici Có vẻ như một lỗi tài liệu sau đó, đặc biệt là vì tài liệu cho Here Documents không đề cập đến việc mở rộng dấu ngoặc nhọn (và nó cũng không xảy ra ở đó trong một thử nghiệm nhanh) mặc dù họ cũng không đề cập đến việc mở rộng dấu ngã (điều này không xảy ra cho <<nhưng làm <<<như vậy *shrug*). Việc mở rộng có và không xảy ra trong tài liệu ở đây và ở đây các chuỗi hơi kỳ lạ đối với tâm trí của tôi.
Etan Reisner

1
Làm thế nào bạn có thể tách các kết quả từ các lần chạy khác nhau với ví dụ như dòng mới?
nirvana-msu

3
Demo: time head -12 <(yes "1") | xargs -n1 -P4 sleepsẽ chạy 12 sleep 1lệnh, 4 lệnh song song. Lệnh sẽ mất 3 giây.
Walter A

66

Với GNU Parallel, bạn sẽ làm được:

parallel script-to-run.sh input/ output/ {} ::: {0..99}

Thêm vào -P8nếu bạn không muốn chạy một công việc trên mỗi lõi CPU.

Ngược xargslại nó sẽ thực hiện Điều đúng đắn, ngay cả khi đầu vào chứa khoảng trắng, 'hoặc "(tuy nhiên, không phải trường hợp ở đây). Nó cũng đảm bảo đầu ra từ các công việc khác nhau không bị trộn lẫn với nhau, vì vậy nếu bạn sử dụng đầu ra thì bạn đảm bảo rằng bạn sẽ không nhận được nửa dòng từ hai công việc khác nhau.

GNU Parallel là một trình song song chung và giúp dễ dàng chạy các công việc song song trên cùng một máy hoặc trên nhiều máy mà bạn có quyền truy cập ssh.

Nếu bạn có 32 công việc khác nhau mà bạn muốn chạy trên 4 CPU, thì một cách đơn giản để chạy song song là chạy 8 công việc trên mỗi CPU:

Lập lịch trình đơn giản

GNU Parallel thay vào đó tạo ra một quá trình mới khi một quá trình kết thúc - giữ cho các CPU hoạt động và do đó tiết kiệm thời gian:

Lập lịch song song GNU

Cài đặt

Nếu GNU Parallel không được đóng gói cho bản phân phối của bạn, bạn có thể thực hiện cài đặt cá nhân mà không yêu cầu quyền truy cập root. Nó có thể được thực hiện trong 10 giây bằng cách làm như sau:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 67bd7bc7dc20aff99eb8f1266574dadb
12345678 67bd7bc7 dc20aff9 9eb8f126 6574dadb
$ md5sum install.sh | grep b7a15cdbb07fb6e11b0338577bc1780f
b7a15cdb b07fb6e1 1b033857 7bc1780f
$ sha512sum install.sh | grep 186000b62b66969d7506ca4f885e0c80e02a22444
6f25960b d4b90cf6 ba5b76de c1acdf39 f3d24249 72930394 a4164351 93a7668d
21ff9839 6f920be5 186000b6 2b66969d 7506ca4f 885e0c80 e02a2244 40e8a43f
$ bash install.sh

Để biết các tùy chọn cài đặt khác, hãy xem http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Tìm hiểu thêm

Xem thêm các ví dụ: http://www.gnu.org/software/parallel/man.html

Xem video giới thiệu: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Xem qua hướng dẫn: http://www.gnu.org/software/parallel/parallel_tutorial.html

Đăng ký danh sách email để nhận hỗ trợ: https://lists.gnu.org/mailman/listinfo/parallel


19
Điều này không trả lời câu hỏi, cũng không chỉ ra lý do tại sao xargs không thể đạt được điều tương tự.
张 实 唯

8
downvote vì xarg đối với tôi làm chính xác như hình ảnh thứ hai cho thấy.
noonex

3
@noonex Bạn có biết rằng không phải ai cũng sử dụng phiên bản xargs mà bạn sử dụng và -P không có trong tất cả các phiên bản của xargs không?
Ole Tange

19
Có lẽ không phải tất cả đều biết rằng câu trả lời này được cung cấp bởi tác giả của GNU song song.
izkeros

1
Bị phản đối do quảng cáo rõ ràng trên một phần mềm không chạy chính xác như được mô tả trong lần thử đầu tiên, do lời nhắc tương tác làm rối loạn hầu hết các tập lệnh.
Daniel Sorichetti
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.