2009-11-05 3 views
3

Хорошо, я бежал POV-Ray на всех демонстрационных версиях, но POV все еще однопоточный и не использовал бы более одного ядра. Итак, я начал думать о решении в BASH.Многопоточное программирование BASH - обобщенный метод?

Я написал общую функцию, которая принимает список команд и запускает их в указанном числе подклассов. Это на самом деле работает, но мне не нравится, как она обрабатывает доступ к следующей команде в поточно- многопроцессной пути:

  • Он принимает в качестве аргумента, файл с командами (1 в каждой строке),
  • Чтобы получить команду "рядом", каждый процесс ("нить") будет:
    • Ждет, пока он не может создать файл блокировки, с: пер $ CMDFILE $ LockFile
    • Прочтите команду m файл,
    • Изменяет $ CMDFILE, удаляя первую строку,
    • Удаляет $ LOCKFILE.

Есть уборщик способ сделать это? Я не мог заставить суб-оболочки правильно читать одну строку из FIFO.


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

Между тем, вот функция, которая обрабатывает получение следующей строки из файла. Как вы можете видеть, он изменяет файл на диске каждый раз, когда он читает/удаляет строку. Это то, что кажется хакерским, но я не придумал ничего лучшего, так как FIFO не работал без setvbuf() в bash.

# 
# Get/remove the first line from FILE, using LOCK as a semaphore (with 
# short sleep for collisions). Returns the text on standard output, 
# returns zero on success, non-zero when file is empty. 
# 
parallel__nextLine() 
{ 
    local line rest file=$1 lock=$2 

    # Wait for lock... 
    until ln "${file}" "${lock}" 2>/dev/null 
    do sleep 1 
    [ -s "${file}" ] || return $? 
    done 

    # Open, read one "line" save "rest" back to the file: 
    exec 3<"$file" 
    read line <&3 ; rest=$(cat<&3) 
    exec 3<&- 

    # After last line, make sure file is empty: 
    ([ -z "$rest" ] || echo "$rest") > "${file}" 

    # Remove lock and 'return' the line read: 
    rm -f "${lock}" 
    [ -n "$line" ] && echo "$line" 
} 
+0

Оставьте свой код! –

+0

Посмотрите на 'lockfile-progs (1)', чтобы узнать, есть ли какая-либо помощь. Проблема с FIFO может быть связана с буферизацией. Некоторые утилиты имеют небуферизованный режим. –

ответ

7
#adjust these as required 
args_per_proc=1 #1 is fine for long running tasks 
procs_in_parallel=4 

xargs -n$args_per_proc -P$procs_in_parallel povray < list 

Обратите внимание на nproc команде скоро в Coreutils будет автоматически определять количество доступных блоков обработки, которые затем могут быть переданы -P

+0

Мой вопрос действительно о программировании в bash, а не просто о том, чтобы задания выполнялись параллельно. Но это хорошая информация - спасибо! – NVRAM

+0

BTW, ** grep -c^processor/proc/cpuinfo **, похоже, отлично работает на Linux, если **/proc ** установлен, хотя у меня нет большого количества машин, на которых можно его протестировать. – NVRAM

+0

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

2

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

С помощью python, например, вы можете создавать реальные потоки с безопасной синхронизацией с помощью семафоров/очередей.

0

Я считаю, что вы на самом деле наводя процессы здесь, а не нарезание резьбы. Я бы порекомендовал искать поддержку потоковой передачи на другом языке сценариев, например perl, python или ruby.

+0

Действительно, это порождает суб-оболочки. Я думал, что в тексте ясно, что я подразумеваю термин «поток» концептуально; Я сделал некоторые изменения, чтобы сделать это более ясным. – NVRAM

+1

Процессорное сканирование довольно дешево в системах на основе Unix, а отдельные процессы часто называют «потоками», неточно. В любом случае отдельные процессы часто лучше, чем потоки, поскольку они более автономны. –

+0

Я согласен, что разветвленные процессы могут быть лучшим подходом, чем потоки. – dlamblin

2

жаль поднять это после того, как так долго, но я кусочки довольно хорошее решение для этого IMO
Он не работает отлично, но он ограничивает скрипт определенным количеством выполняемых дочерних задач, а затем ждет всех остальных в конце.

#!/bin/bash 

pids=() 
thread() { 
    local this 
    while [ ${#} -gt 6 ]; do 
    this=${1} 
    wait "$this" 
    shift 
    done 
    pids=($1 $2 $3 $4 $5 $6) 
} 
for i in 1 2 3 4 5 6 7 8 9 10 
do 
    sleep 5 & 
    pids=(${pids[@]-} $(echo $!)) 
    thread ${pids[@]} 
done 
for pid in ${pids[@]} 
do 
    wait "$pid" 
done 

, кажется, отлично работает для того, что я делаю (обработка параллельно выгрузку кучу файлов сразу) и удерживает его от взлома моего сервера, при этом убедившись, что все файлы будут загружены до его завершения сценарий

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