การรันโปรแกรมแบบขนานโดยใช้ xargs


86

ขณะนี้ฉันมีสคริปต์ปัจจุบัน

#!/bin/bash
# script.sh

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

ฉันต้องการรันแบบขนานโดยใช้ xargs ฉันเหนื่อย

script.sh | xargs -P8

แต่การดำเนินการข้างต้นจะดำเนินการเพียงครั้งเดียวในเวลานั้น ไม่มีโชคกับ -n8 ด้วย การเพิ่ม & ที่ท้ายบรรทัดเพื่อดำเนินการในสคริปต์สำหรับลูปจะพยายามเรียกใช้สคริปต์ 99 ครั้งพร้อมกัน ฉันจะดำเนินการลูปเพียง 8 ครั้งในขณะนั้นได้อย่างไรรวมถึง 100


นั่นคือสิ่งที่ฉันอยากทำในตอนแรก แต่ต้องใช้ xargs เพราะฉันใช้ Windows ฉันไม่สามารถให้ GNU Parallel ทำงานบน Windows ได้
Olivier

สคริปต์นั้นเรียกตัวเองหรือคุณแค่สับสนชื่อเมื่อคุณถามที่นี่?
Etan Reisner

ขออภัยควรเรียกสคริปต์อื่น ฉันจะแก้ไข
Olivier

คำตอบสำหรับstackoverflow.com/questions/3321738/…มีความเกี่ยวข้องที่นี่
Etan Reisner

คำตอบ:


129

จากxargsหน้าคน:

หน้าคู่มือนี้มีเอกสาร xargs เวอร์ชัน GNU xargs อ่านรายการจากอินพุตมาตรฐานคั่นด้วยช่องว่าง (ซึ่งสามารถป้องกันได้ด้วยเครื่องหมายคำพูดคู่หรือเดี่ยวหรือแบ็กสแลช) หรือขึ้นบรรทัดใหม่และเรียกใช้คำสั่ง (ค่าเริ่มต้นคือ / bin / echo) หนึ่งครั้งหรือมากกว่านั้นโดยมีอาร์กิวเมนต์เริ่มต้นตามมา ตามรายการที่อ่านจากอินพุตมาตรฐาน บรรทัดว่างบนอินพุตมาตรฐานจะถูกละเว้น

ซึ่งหมายความว่าสำหรับตัวอย่างของคุณคือการรอคอยและการเก็บรวบรวมทั้งหมดของการส่งออกจากสคริปต์ของคุณแล้วทำงานxargs echo <that output>ไม่ใช่ทั้งหมดที่มีประโยชน์หรือสิ่งที่คุณต้องการ

-nอาร์กิวเมนต์เป็นวิธีการที่หลายรายการจากการป้อนข้อมูลที่จะใช้กับคำสั่งที่ได้รับการทำงานในแต่ละ (ไม่มีอะไรด้วยตัวเองเกี่ยวกับความเท่าเทียมที่นี่)

ในการทำสิ่งที่คุณต้องการxargsคุณจะต้องทำสิ่งนี้เพิ่มเติม (ยังไม่ทดลอง):

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

ซึ่งแตกสลายเช่นนี้.

  • printf %s\\n {0..99}- พิมพ์จำนวนหนึ่งต่อเส้นจากการ099
  • วิ่ง xargs
    • รับไม่เกินหนึ่งอาร์กิวเมนต์ต่อบรรทัดคำสั่งการรัน
    • และรันได้ถึงแปดกระบวนการในแต่ละครั้ง

8
จริงๆแล้วคุณไม่จำเป็นต้องใส่อาร์กิวเมนต์แยกบรรทัด การแบ่งคำ xargs ดังนั้นecho {0..99} |จะทำงานก็เช่นกัน <<<{0..99}ดูเหมือนจะไม่ทำงาน แม้ว่าจะ<<<wordมีการบันทึกเป็นคำขยายวงเล็บปีกกา แต่ก็ไม่ได้ทำเช่นนั้นกับ bash ทุกรุ่นที่ฉันมีประโยชน์
rici

1
@rici ดูเหมือนข้อผิดพลาดของเอกสารโดยเฉพาะอย่างยิ่งเนื่องจากเอกสารสำหรับ Here Documents ไม่ได้กล่าวถึงการขยายวงเล็บปีกกา (และไม่ได้เกิดขึ้นที่นั่นในการทดสอบอย่างรวดเร็ว) แม้ว่าพวกเขาจะไม่ได้กล่าวถึงการขยายตัวหนอน (ซึ่งไม่ได้เกิดขึ้น สำหรับ<<แต่ทำ<<<เพื่อ*shrug*) การขยายที่เกิดขึ้นและไม่เกิดขึ้นในเอกสารที่นี่และสตริงที่นี่เป็นเรื่องแปลกสำหรับฉัน
Etan Reisner

1
คุณจะแยกผลลัพธ์จากการวิ่งที่แตกต่างกันด้วยเช่นขึ้นบรรทัดใหม่ได้อย่างไร
n Nirvana-msu

4
Demo: time head -12 <(yes "1") | xargs -n1 -P4 sleepจะรัน 12 sleep 1คำสั่ง 4 ขนาน คำสั่งจะใช้เวลา 3 วินาที
Walter A

66

ด้วย GNU Parallel คุณจะทำ:

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

เพิ่มใน-P8กรณีที่คุณไม่ต้องการรันหนึ่งงานต่อแกน CPU

ตรงข้ามxargsมันจะทำสิ่งที่ถูกต้องแม้ว่าอินพุตจะมีช่องว่าง "หรือ" (ไม่ใช่ในกรณีนี้) นอกจากนี้ยังตรวจสอบให้แน่ใจว่าเอาต์พุตจากงานที่แตกต่างกันไม่ได้ผสมกันดังนั้นหากคุณใช้เอาต์พุตที่คุณเป็น รับประกันว่าคุณจะไม่ได้รับครึ่งแถวจากสองงานที่แตกต่างกัน

GNU Parallel เป็นเครื่องขนานทั่วไปและทำให้ง่ายต่อการเรียกใช้งานแบบขนานบนเครื่องเดียวกันหรือบนเครื่องหลายเครื่องที่คุณมีสิทธิ์เข้าถึง ssh

หากคุณมีงานที่แตกต่างกัน 32 งานที่คุณต้องการรันบน CPU 4 ตัววิธีการต่อขนานแบบตรงไปตรงมาคือการรัน 8 งานบน CPU แต่ละตัว:

การตั้งเวลาที่เรียบง่าย

GNU Parallel จะสร้างกระบวนการใหม่แทนเมื่อเสร็จสิ้น - ทำให้ซีพียูทำงานอยู่และประหยัดเวลา:

การตั้งเวลาแบบขนาน GNU

การติดตั้ง

หาก GNU Parallel ไม่ได้ถูกรวมไว้สำหรับการแจกจ่ายของคุณคุณสามารถทำการติดตั้งส่วนบุคคลซึ่งไม่จำเป็นต้องเข้าถึงรูท สามารถทำได้ภายใน 10 วินาทีโดยทำสิ่งนี้:

$ (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

สำหรับตัวเลือกการติดตั้งอื่น ๆ โปรดดูที่http://git.savannah.gnu.org/cgit/parallel.git/tree/README

เรียนรู้เพิ่มเติม

ดูตัวอย่างเพิ่มเติม: http://www.gnu.org/software/parallel/man.html

ชมวิดีโอแนะนำ: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

ดูบทช่วยสอน: http://www.gnu.org/software/parallel/parallel_tutorial.html

ลงทะเบียนรายชื่ออีเมลเพื่อรับการสนับสนุน: https://lists.gnu.org/mailman/listinfo/parallel


19
สิ่งนี้ไม่ได้ตอบคำถามหรือชี้ให้เห็นว่าทำไม xargs ไม่สามารถบรรลุสิ่งเดียวกันได้
张实唯

8
downvote เพราะ xarg สำหรับฉันทำตามที่ภาพที่สองแสดง
noonex

3
@noonex คุณทราบหรือไม่ว่าไม่ใช่ทุกคนที่ใช้ xargs เวอร์ชันที่คุณใช้และ -P นั้นไม่ได้อยู่ใน xargs ทุกเวอร์ชัน
Ole Tange

20
อาจไม่ใช่ทุกคนที่ทราบว่าคำตอบนี้จัดทำโดยผู้เขียน GNU parallel
izkeros

1
ถูกลดคะแนนเนื่องจากมีการโฆษณาที่ชัดเจนในซอฟต์แวร์ที่ทำงานไม่ถูกต้องตามที่อธิบายไว้ในความพยายามครั้งแรกเนื่องจากข้อความแจ้งแบบโต้ตอบที่ทำให้สคริปต์ส่วนใหญ่ยุ่งเหยิง
Daniel Sorichetti
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.