2016-09-26 3 views
1

У меня в настоящее время есть скрипт bash, script.sh, с двумя вложенными циклами. Первый перечисляет возможные значения а, а второе перечисляет возможные значения для б, какИспользование xargs для параллельных скриптов Python

#!/bin/sh 
for a in {1..10} 
do 
    for b in {1..10} 
    do 
     nohup python script.py $a $b & 
    done 
done 

Таким образом, это порождает от 100 процессов Python под управлением script.py, по одному для каждого (а, б) пару. Однако моя машина имеет только 5 ядер, поэтому я хочу ограничить количество процессов в 5, чтобы избежать перекоса/расточительного переключения. Цель состоит в том, что я всегда выполняю 5 процессов, пока не будут выполнены все 100 процессов.

xargs, кажется, один из способов сделать это, но я не знаю, как передать эти аргументы в xargs. Я проверил другие подобные вопросы, но не понимаю окружающий басский жаргон достаточно хорошо, чтобы знать, что происходит. Например, я попытался

seq 1 | xargs -i --max-procs=5 bash script.sh 

, но это, кажется, не делать ничего - script.sh работает, как и раньше, и по-прежнему нерестится от 100 процессов.

Я предполагаю, что я не понимаю, как работает xargs.

Спасибо!

+1

'xargs' не может, и не измените, как его подпроцессы * начать их собственных детей *; скорее, он обеспечивает контроль над тем, как он начинает свои подпроцессы. –

+1

В случае с Python я бы предложил использовать модуль «многопроцессорности» Python вместо 'xargs'. Или, альтернативно, утилиту GNU 'parallels'. https://docs.python.org/3/library/multiprocessing.html – Wolph

+0

@Wolph, я определенно согласен повторно: многопроцессорность. Что касается GNU parallel - это более сложная и более сложная кодовая база, чем «xargs», которая является моделью простоты в сравнении. Учитывая предпочтение Pythonist для простоты, я бы счел xargs очевидным выбором среди этих двух. :) –

ответ

4

Это на самом деле больше похоже:

#!/bin/bash 
for a in {1..10}; do 
    for b in {1..10}; do 
    printf '%s\0' "$a" "$b" 
    done 
done | xargs -0 -x -n 2 -P 5 python script.py 

Обратите внимание, что нет никакого nohup, ни какого-либо & - отслеживать количество одновременных вызовов, xargs должны быть непосредственно выполнением сценария Python, и этот процесс не может выйти до завершения.

Нестандартное (но широко доступное) расширение требуется для ввода в форме с нулевым значением (как создано с помощью printf '%s\0'); это обеспечивает правильное поведение с аргументами, имеющие пробелы, кавычки, обратные слэши и т.д.

также нестандартным -P 5 устанавливает максимальное количество процессов (в пути чуть более компактен, чем --max-procs=5, который поддерживается на GNU, но не современный BSD xargs).

-n 2 указывает, что каждый экземпляр скрипта Python получает только два аргумента, таким образом, начиная один на пару входов.

-x (используется совместно с -n 2) указывает, что если одному экземпляру Python не могут быть предоставлены два аргумента (например, если аргументы настолько велики, что оба они не могут вписаться в одну командную строку) это должно рассматриваться как сбой, а не вызов экземпляра Python только с одним аргументом.

+0

Сбой в Cygwin с: -bash: fi: строка 4: синтаксическая ошибка около неожиданного токена 'for ' -bash: fi: строка 4:' для b в {1..10}' –

+0

@OleTange, мне не хватало некоторых '; do's - это исправлено сейчас. –

1

Если вы используете Баш, то следующее должно работать:

#!/bin/bash 

for a in {1..10} 
do 
    for b in {1..10} 
    do 
     if [ `jobs | wc -l` -lt 6 ]; then # less than 6 background jobs 
      nohup python script.py $a $b & 
     else 
      wait -n # wait for any background job to terminate 
     fi 
    done 
done 
+0

Извлеките 'nohup', если вы хотите' wait' или 'jobs' работать. –

+0

@CharlesDuffy Он также работает с 'nohup'. Протестировано с помощью 'nohup sleep 5 &' + 'wait'. –

+0

Предоставлено - это кузена 'disown', созданная оболочкой, которая имела бы такой эффект. –

1

GNU Parallel делается для именно этих видов работ:

parallel python script.py ::: {1..10} ::: {1..10} 

Если вам нужно $ а и $ Ь размещены по-разному вы можете использовать {1} и {2} для обозначения двух входных источников:

parallel python script.py --option-a {1} --option-b {2} ::: {1..10} ::: {1..10} 

GNU Parallel является общим paralleliz er и позволяет легко запускать задания параллельно на одном компьютере или на нескольких машинах, к которым у вас есть доступ ssh.Он часто может заменить петлю for.

Если у вас есть 32 различных заданий, которые вы хотите работать на 4-х процессоров, прямо вперед способ распараллеливания является выполнение 8 заданий на каждом CPU:

Simple scheduling

GNU Parallel вместо порождает новый процесс, когда один заканчивается - поддержание процессоров активным и тем самым экономя время:

GNU Parallel scheduling

Установка

Если GNU Parallel не упакован для вашего дистрибутива, вы можете выполнить личную установку, которая не требует доступа root. Это может быть сделано в течение 10 секунд, делая это:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash 

Для других вариантов установки см 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

Прогулка по t он учебник: http://www.gnu.org/software/parallel/parallel_tutorial.html

Зарегистрируйтесь на список адресов электронной почты, чтобы получить поддержку: https://lists.gnu.org/mailman/listinfo/parallel

Смежные вопросы