Паралельний запуск програм за допомогою xargs


85

На даний момент я маю поточний сценарій.

#!/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
Олів'є

Цей сценарій називає себе, чи ви просто переплутали імена, коли запитали тут?
Etan Reisner

На жаль, він повинен викликати інший сценарій. Я виправлю це
Олів'є

Відповідь на stackoverflow.com/questions/3321738/… тут актуальна.
Etan Reisner

Відповіді:


128

Зі xargsсторінки користувача:

Ця сторінка керівництва документує GNU-версію xargs. 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}- Надрукуйте одне число на рядок від 0до 99.
  • Біжи xargs
    • беручи не більше одного аргументу за командний рядок запуску
    • і запускати до восьми процесів одночасно

7
Насправді вам не потрібно розміщувати аргументи в окремих рядках; xargs розбиває слова. Так echo {0..99} |би працювало так само добре. <<<{0..99}здається, не працює; хоча <<<wordце документується як слово, що розширює фігурні дужки, це не робиться з жодною версією bash, яка мені під рукою.
Річі

1
@rici Схоже на помилку документації, тим більше, що в документації для Here Documents не згадується розширення фігурних дужок (і там це не відбувається в швидкому тесті), хоча вони також не згадують розширення тильди (чого не відбувається) для, <<але робить для <<<цього *shrug*). Розширення, які робляться і не відбуваються в цих документах і тут рядках, на мій погляд трохи дивні.
Etan Reisner

1
Як можна відокремити результати від різних прогонів, наприклад, за допомогою нових рядків?
nirvana-msu

3
Демонстрація: time head -12 <(yes "1") | xargs -n1 -P4 sleepбуде виконувати 12 sleep 1команд, 4 паралельно. Команда займе 3 секунди.
Вальтер A

66

За допомогою GNU Parallel ви робите:

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

Додайте, -P8якщо ви не хочете виконувати одне завдання на ядро ​​процесора.

Навпаки xargsце буде робити The Right Thing, навіть якщо вхідні дані містять пробіл, ', або "(хоча це не так). Він також гарантує, що результати з різних завдань не змішуються разом, тому, якщо ви використовуєте вихідні дані, гарантуємо, що ви не отримаєте половину лінії від двох різних робіт.

GNU Parallel - загальний паралелізатор, що дозволяє легко виконувати завдання паралельно на одній машині або на декількох машинах, до яких у вас є доступ до ssh.

Якщо у вас є 32 різних завдання, які ви хочете запустити на 4 процесорах, прямий спосіб паралелізації - це 8 завдань на кожному процесорі:

Просте планування

Натомість 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
Це не відповідає ні на запитання, ні вказує на те, чому ксарг не може досягти того самого.
张 实 唯

8
проти, тому що xarg для мене робить саме так, як показано на другому малюнку.
noonex 07

3
@noonex Чи відомо вам, що не всі використовують версію xargs, яку ви використовуєте, і що -P є не у всіх версіях xargs?
Оле Танг

19
Можливо, не всім відомо, що цю відповідь дає автор GNU паралельно.
izkeros

1
Проголосували проти через чітку рекламу програмного забезпечення, яке не працює належним чином, як було описано при перших спробах, через інтерактивне підказку, яке псує більшість сценаріїв.
Даніель Сорічетті
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.