LINUX.ORG.RU
 
Davidov

семафоры для bash?


0

0

Есть большой список команд, которые нужно вызвать.

Есть простой способ распараллелить их на нужное количество потоков на bash/shell?
Перемещено cavia_porcellus из Talks


[#]  
Davidov

Re: семафоры для bash?

Перенесите, плиз, в Development.

**** ()
[#]  

Re: семафоры для bash?

Проще не баш использовать, а мейкфайлы сделать через cmake например.

* ()
[#]  

Re: семафоры для bash?

Причем тут семафоры?

for c in cmds; do
$c &
done

wait

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 05.06.2009 19:35:52  
Davidov

Re: семафоры для bash?

И как здесь контролируется количество потоков? Мне нужно по количеству процессоров - 8.

Сейчас сделал просто lock file на каждую команду и запустил 8 скриптов одновременно, пусть соревнуются. Но должен быть способ проще.

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 05.06.2009 19:44:23  

Re: семафоры для bash?

> И как здесь контролируется количество потоков?

Процессов, не нитей. И оно никак не контролируется..

> Мне нужно по количеству процессоров - 8.

Я сильно сомневаюсь, что оно тебе нужно, поскольку планирование лучше оставить ядру... ОК, ты хочешь поддерживать 8 процессов запущенными постоянно, один завершился - другой запущен?

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 05.06.2009 19:53:36  
Davidov

Re: семафоры для bash?

>Процессов, не нитей

Оговорился.

>ты хочешь поддерживать 8 процессов запущенными постоянно, один завершился - другой запущен?

Да. Ресурсоёмкие задачки.

**** ()
[#]  

Re: семафоры для bash?

Попробуй обрабатывать SIGCHLD, но вообще это задача для GNU Make. Или, если устраивает эффективность на 90%, можно попробовать запускать задачи пачками по 8 штук и запускать каждую пачку только после окончания предыдущей.

***** ()
[#] Ответ на: Re: семафоры для bash? от AEP 05.06.2009 20:07:25  

Re: семафоры для bash?

> Попробуй обрабатывать SIGCHLD,

Не обрабатывается почему-то :/

> запускать задачи пачками по 8 штук и запускать каждую пачку только после окончания предыдущей.

Это неспортивно :)

***** ()
[#] Ответ на: Re: семафоры для bash? от AEP 05.06.2009 20:07:25  
Davidov

Re: семафоры для bash?

>GNU Make

Надо попробовать. Нужно писать как-то вроде: all: task1 task2 .. taskN и запускать с -j8, да?

Команд, кстати около миллиона. Текущая реализация с flock, вроде бы, создаёт большую нагрузку на fs; хотя м.б. проблема не с flock.

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 05.06.2009 19:57:49  
dikiy

Re: семафоры для bash?

>>ты хочешь поддерживать 8 процессов запущенными постоянно, один завершился - другой запущен?

>Да. Ресурсоёмкие задачки.

запускай сразу все. Только первым 8-и nice - 0, следующей восьмерке nice - 1 и т.д.

*** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 05.06.2009 20:44:50  
dikiy

Re: семафоры для bash?

>Команд, кстати около миллиона.

ладно. мой предыдущий пост считать недействительным )

*** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 05.06.2009 20:11:26  

Re: семафоры для bash?

Как выяснилось, SIGCHLD таки можно обрабатывать, но толку от этого нет...

Вот вариант без сигналов и прочей магии, он грязноватый, но идею иллюстрирует:

cmds="
/bin/sleep 1\n
/bin/sleep 1\n
/bin/sleep 1\n
/bin/sleep 1\n
/bin/sleep 7\n
/bin/sleep 8\n
/bin/sleep 9\n
/bin/sleep 10\n
/bin/sleep 11; echo Типа всё\n"

# команды передаются на стандартный вввод
echo -e $cmds | \
(MAXPROCS=8
 nalive=$MAXPROCS
 eof="false"
 nextcmd() {
   local c
   read c
   if [ -z "$c" ]; then
     eval $eof || echo No more commands to run
     eof="true"
   else
     echo Adding $c
     eval "$c; echo -n x >exits" &
     nalive=$[nalive + 1]
   fi
 }
 get_exits() {
   local x
   x=$(cat exits)
   echo $[$(echo "$x" | wc -c) - 1]
 }
 # создаем FIFO, через которое сообщается о завершении команд
 mkfifo exits
 # пускаем первые MAXPROCS команд
 echo Priming...
 for n in $(seq 1 $MAXPROCS); do
   read c
   echo $c
   eval "$c; echo -n x >exits" &
 done
 # ждем сообщения о завершении команд, и запускаем им на замену новые
 while :; do
   nalive=$[$nalive - $(get_exits)]
   for i in $(seq $nalive $[$MAXPROCS - 1]); do
     nextcmd
   done
   eval $eof && break
 done
 echo Waiting for $nalive unfinished processes...
 while :; do
   nalive=$[$nalive - $(get_exits)]
   [ $nalive -eq 0 ] && break
   echo $nalive left
 done
 wait
 rm exits)

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 06.06.2009 2:37:06  
Davidov

Re: семафоры для bash?

Спасибо. Вообще кошмар, лучше такое на питоне писать, наверное ;)


sem = threading.Semaphore(8)

for cmd in commands:
  sem.acquire()
  thread.start_new_thread(call_cmd, (cmd,))

**** ()
[#]  

Re: семафоры для bash?

cmd1 < /dev/null > /dev/null | cmd2 < /dev/null > /dev/null | cmd3 < /dev/null > /dev/null | cmd4 < /dev/null > /dev/null | cmd5 < /dev/null > /dev/null | cmd6 < /dev/null > /dev/null | cmd7 < /dev/null > /dev/null | cmd8 < /dev/null > /dev/null

p.s. ответ автосгенерирован:)

***** ()
[#] Ответ на: Re: семафоры для bash? от dilmah 06.06.2009 17:10:12  
Davidov

Re: семафоры для bash?

Так не об этом же речь!

Ну вот например:

for f1 in filelist; do
  for f2 in filelist; do
    if [[ "$f1" < "$f2" ]]; then
      diff $f1 $f2 > diff_$f1_$f2.txt
    fi
  done
done

Допустим filelist - это 800 файлов. На машине 8 процессоров; хочется, чтобы одновременно всегда выполнялись 8 diff'ов.

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 06.06.2009 17:18:40  
true_admin

Re: семафоры для bash?

раз в секунду проверяешь скока диффов запущено и плодишь новые если их не хватает. Как вариант можно отслеживать статус чайлдов.

И не обязательно на баше такое писать, вполне можно и python/perl.

***** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 06.06.2009 17:18:40  

Re: семафоры для bash?

> Допустим filelist - это 800 файлов. На машине 8 процессоров; хочется, чтобы одновременно всегда выполнялись 8 diff'ов.

я ж их в пайп объединил. Пайпы исполняются последовательно только в мс-дос

***** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 06.06.2009 13:22:08  

Re: семафоры для bash?

> Вообще кошмар

Кошмаром было это писАть %) Шелл приспособлен для обработки потоков данных,
а не для планирования.

> for cmd in commands:

> sem.acquire()

> thread.start_new_thread(call_cmd, (cmd,))


Ну это же не вся прога...

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 06.06.2009 17:32:47  
Davidov

Re: семафоры для bash?

>Ну это же не вся прога...

import thread
import threading
import subprocess

def call_cmd(cmd):
    subprocess.call(cmd.split())
    sem.release()

commands = ['sleep 10', 'sleep 5', 'sleep 12'] * 20

sem = threading.Semaphore(8)

for cmd in commands:
    sem.acquire()
    thread.start_new_thread(call_cmd, (cmd,))

**** ()
[#]  

Re: семафоры для bash?

А может запускать скрипт под отдельным пользователем, у которого ограничено количество процессов (ulimit -u)?

Это конечно, не идеальное решение, поскольку два таких скрипта не запустишь.

Не, это совсем плохое решение, ибо скрипт будет завершаться с ошибкой при попытке форкнуться.

* ()
[#] Ответ на: Re: семафоры для bash? от dilmah 06.06.2009 17:26:16  
Davidov

Re: семафоры для bash?

>Пайпы исполняются последовательно только в мс-дос

Этот вариант работает только пачками по восемь, и не понимает, что одна команда может завершиться раньше; и в таком случае нужно сразу запускать следующую.

**** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 06.06.2009 2:37:06  
Davidov

Re: семафоры для bash?

Погоди, а разве оно не будет постоянно крутиться в цикле?

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 06.06.2009 17:59:27  

Re: семафоры для bash?

> commands = ['sleep 10', 'sleep 5', 'sleep 12'] * 20

> for cmd in commands:

Ну ты ж не станешь весь миллион команд держать во внутреннем массиве? :)

> Погоди, а разве оно не будет постоянно крутиться в цикле?

Вторая часть конвейера - это автономная прога, которая читает команды для исполнения с stdin. Там встроен цикл, да. Проверка на EOF, все дела.

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 06.06.2009 18:27:32  
Davidov

Re: семафоры для bash?

>Ну ты ж не станешь весь миллион команд держать во внутреннем массиве? :)

Во-первых, могу :) Во-вторых, можно сделать файл с командами. В-третьих, на самом деле команды выполняются для каждого файла в директории (то есть эдакий многопоточный find -exec). И, в-четвёртых, в твоём примере это тоже опущено :)

**** ()
[#] Ответ на: Re: семафоры для bash? от gorilych 06.06.2009 18:27:08  
Davidov

Re: семафоры для bash?

>вот здесь решение подобной задачи:

О... спасибо.

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 06.06.2009 18:32:40  

Re: семафоры для bash?

> И, в-четвёртых, в твоём примере это тоже опущено :)

ненене, в моем примере всё честно читается со stdin. Я веду к тому, что на Питоне прога вряд ли будет более чем в 2 раза короче (хотя будет яснее, конечно).

***** ()
[#] Ответ на: Re: семафоры для bash? от gorilych 06.06.2009 18:27:08  

Re: семафоры для bash?

> вот здесь решение подобной задачи:

Вроде оно заканчивается на "I am pretty much stuck at where to begin next" и совете использовать Питон? %)

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 06.06.2009 18:41:30  
Davidov

Re: семафоры для bash?

import thread
import threading
import subprocess
import sys

def call_cmd(cmd):
    subprocess.call(cmd.split())
    sem.release()

sem = threading.Semaphore(8)

for cmd in sys.stdin:
    sem.acquire()
    thread.start_new_thread(call_cmd, (cmd,))

Кажется, это более, чем в 2 раза )

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 06.06.2009 18:51:32  

Re: семафоры для bash?

> Кажется, это более, чем в 2 раза )

В общем да, но оно при старте читает весь миллион команд :) Который, теоретически, может быть еще не весь готов (ага, я придираюсь).

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 06.06.2009 19:04:20  
Davidov

Re: семафоры для bash?

В последнем приведённом варианте из stdin читается; и, вроде, не весь миллион а построчно :)

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 06.06.2009 18:51:32  
Davidov

Re: семафоры для bash?

import thread, threading, subprocess, sys

sem = threading.Semaphore(8)

for cmd in sys.stdin:
    sem.acquire()
    thread.start_new_thread(lambda:(subprocess.call(cmd.split()), sem.release()), ())


Уже почти похоже на перл ;) Интересно, порядок вычисления аргументов в списке фиксированный? Или есть другой способ имитации сишного оператора запятая?  

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 07.06.2009 12:26:31  

Re: семафоры для bash?

>В последнем приведённом варианте из stdin читается; и, вроде, не весь миллион а построчно :)

Коонструкция for cmd in sys.stdin читает весь stdin до EOF, и потом выдает прочитанное построчно (python 2.5.2 из Lenny).

> порядок вычисления аргументов в списке фиксированный? Или есть другой способ имитации сишного оператора запятая?

Не надо устраивать OPCC :)

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 07.06.2009 14:43:45  
OxiD

Re: семафоры для bash?

может проще написать коротенькую программку на С которая будет работать с SysV семафорами? и вызывать ее из скрипта.. типа sem $KEY $OPERATION ?

** ()
[#] Ответ на: Re: семафоры для bash? от OxiD 07.06.2009 16:33:32  

Re: семафоры для bash?

> Может проще написать коротенькую программку на С которая будет работать с SysV семафорами?

Нет. Проще - на Питоне. Скрипт, который я написал - это курьез. Он работает, но в нем наверняка куча проблем с escaping'ом, он довольно длинный, с неочевидными вызовами... в общем, решить задачу на шелле можно, но только в крайнем случае.

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 07.06.2009 17:19:31  
OxiD

Re: семафоры для bash?

я не знаток питона но мне кажется что его семофоры это posix кототорые работают только для потоков, учитывая все что вы сами пишете про возможные проблемы, наверное проще написать короткую утилитку на Ц. Даже писать не надо она уже есть в примерах, кажется у стивенса. Плюс питон не входит в LSB, перл который входит, обычно собран без тредов и придется опять юзать сис5.. + те же проблемы с эскейпингом... вообщем не знаю, но мне кажется мой подход проще и лучше вписывается в систему полностью реализованную на баше.

** ()
[#] Ответ на: Re: семафоры для bash? от OxiD 07.06.2009 17:52:57  

Re: семафоры для bash?

> мне кажется что его семофоры это posix кототорые работают только для потоков

Да, но это неважно в данном случае. Да и по-любому есть модуль os, в нем - нормальные spawn и wait, которых нет в шелле.

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

За исключением того, что она не полностью на баше.

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 07.06.2009 18:01:32  
OxiD

Re: семафоры для bash?

за исключением того что бОльшая часть возможностей баш написана на С

//ни надо флейма, это шутко, я просто высказал точку зрения :)

** ()
[#]  

Re: семафоры для bash?

а, ну если по теме, но на чистом шелле можно иметь семафоры и прочую синхронизацию -- с помощью mv(1)

например, спинлок:

  while ! mv $lock_file ${lock_file}.locked 2> /dev/null; do
    true
  done

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 07.06.2009 14:43:45  
Davidov

Re: семафоры для bash?

>Коонструкция for cmd in sys.stdin читает весь stdin до EOF, и потом выдает прочитанное построчно (python 2.5.2 из Lenny).

Там что-то более хитрое. Попытка подать 100-мегабайтный файл на вход скрипта с таким циклом не показала увеличения занимаемой памяти.

**** ()
[#] Ответ на: Re: семафоры для bash? от dilmah 07.06.2009 19:53:32  
Davidov

Re: семафоры для bash?

А чем mv лучше flock? И, честно говоря, я не совсем понимаю, как сделать семафор со значением 8, например, при помощи mv.

**** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 07.06.2009 17:19:31  
Davidov

Re: семафоры для bash?

>Нет. Проще - на Питоне. Скрипт, который я написал - это курьез. Он работает, но в нем наверняка куча проблем с escaping'ом, он довольно длинный, с неочевидными вызовами... в общем, решить задачу на шелле можно, но только в крайнем случае.

Кстати, как выяснилось, приведённый мной скрипт работает неправильно :)

http://bugs.python.org/issue1731717

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 07.06.2009 23:27:47  
Davidov

Re: семафоры для bash?

>http://bugs.python.org/issue1731717

Я не уверен, что это именно этот баг; но похоже subprocess.call не thread-safe; вместо двух разных команд иногда одна выполняется два раза.

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 07.06.2009 23:25:14  

Re: семафоры для bash?

> А чем mv лучше flock?

тем что mv это позикс:) В BSD вместо flock shlock.

***** ()
[#] Ответ на: Re: семафоры для bash? от tailgunner 07.06.2009 18:01:32  
OxiD

Re: семафоры для bash?

кстати ту программку о которой я говорил можно написать на питоне с помощью модуля os :)

** ()
[#]  
www_linux_org_ru

Re: семафоры для bash?

я так и не понял, почему от make -j8 отказались.

**** ()
[#] Ответ на: Re: семафоры для bash? от www_linux_org_ru 08.06.2009 2:32:54  
Davidov

Re: семафоры для bash?

>я так и не понял, почему от make -j8 отказались.

Да не отказались. Хотя я думаю, make тоже загрузит все 1M команд в память. Наверное, это не очень хорошо.

**** ()
[#] Ответ на: Re: семафоры для bash? от Davidov 07.06.2009 23:22:35  
const86

Re: семафоры для bash?

>>Коонструкция for cmd in sys.stdin читает весь stdin до EOF, и потом выдает прочитанное построчно (python 2.5.2 из Lenny).

>Там что-то более хитрое. Попытка подать 100-мегабайтный файл на вход скрипта с таким циклом не показала увеличения занимаемой памяти.

Там итератор и эта конструкция действительно читает по одной строке. А у tailgunner'а в Lenny странный питон.

***** ()
[#] Ответ на: Re: семафоры для bash? от const86 08.06.2009 15:31:54  

Re: семафоры для bash?

> Там итератор и эта конструкция действительно читает по одной строке

Версия твоего Python?

***** ()