Управление потоком файловых операций Python (или, может быть, Linux) в целом или блокировка файла - PullRequest
2 голосов
/ 22 января 2012

Я использую кластер компьютеров для параллельных вычислений.Мой домашний каталог является общим для всего кластера.На одной машине у меня есть код ruby, который создает скрипт bash, содержащий команду вычисления, и записывает скрипт, скажем, в ~ / q / каталог.Сценарии называются * .worker1.sh, * .worker2.sh и т. Д.

На других 20 машинах у меня запущено 20 кодов python (по одному на каждой машине), которые (постоянно) проверяют ~ / q/ directory и ищите задания, которые принадлежат этому компьютеру, используя код Python, подобный следующему:

jobs = glob.glob('q/*.worker1.sh')
[os.system('sh ' + job + ' &') for job in jobs]

Для некоторого дополнительного контроля код ruby ​​создаст пустой файл, такой как workeri.start (i = 1..20) в каталоге q после того, как он запишет скрипт bash в каталог q, код python проверит этот «стартовый» файл перед запуском вышеуказанного кода.И в сценарии bash, если команда завершается успешно, сценарий bash создаст пустой файл, такой как 'workeri.sccuess', код python проверяет этот файл после запуска вышеуказанного кода, чтобы убедиться, что вычисление завершено успешно.Если python обнаружит, что вычисление завершилось успешно, он удалит файл 'start' в каталоге q, поэтому код ruby ​​знает, что задание успешно завершено.После того, как сценарий 20 bash полностью завершен, код ruby ​​создаст новый сценарий bash, а python прочитает и выполнит новые сценарии и т. Д.

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

Теперь вопрос: я ожидаю, что 20 заданий будут работать параллельно.Общее время для завершения 20 заданий будет не намного больше, чем время для завершения одного задания.Тем не менее, кажется, что эти задания выполняются последовательно, а время намного дольше, чем я ожидал.

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

Я не уверен, так ли это.Если я разделю скрипты bash на разные каталоги и позволю коду python на разных машинах читать и писать разные каталоги, решит ли это проблему?Или есть другие причины, вызывающие проблему?

Большое спасибо за любые предложения!Дайте мне знать, если я ничего не объяснил.

Дополнительная информация: мой домашний каталог находится в / home / my_group / my_home, вот информация о монтировании: / vol / my_group в / home /my_group тип nfs (rw, nosuid, nodev, noatime, tcp, timeo = 600, retrans = 2, rsize = 65536, wsize = 65536, addr = ...)

Я говорю постоянно проверять каталог q,что означает цикл Python, как это:

While True:
    if 'start' file exists:
        find the scripts and execute them as I mentioned above

Ответы [ 2 ]

1 голос
/ 22 января 2012

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

Хотя это не совсем то, чтовы спросили, вы действительно должны действительно рассмотреть возможность решения вашей проблемы на этом уровне, поскольку использование какой-либо общей очереди сообщений, вероятно, будет много проще в управлении и отладке, чем полагаться насемантика блокировки определенной сетевой файловой системы.

Самым простым решением для настройки и запуска из моего опыта является redis на компьютере, на котором в данный момент выполняется скрипт Ruby, который создает задания.Это должно быть буквально так же просто, как загрузить исходный код, скомпилировать и запустить его.Как только сервер Redis запущен и работает, вы изменяете свой код, чтобы добавить свои команды вычисления в один или несколько списков Redis.В ruby ​​вы должны использовать библиотеку redis-rb следующим образом:

require "redis"

redis = Redis.new
# Your other code to build up command lists...
redis.lpush 'commands', command1, command2...

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

redis.lpush 'jobs:machine1', command1
# etc.

Затем в своем коде Python вы можете использовать redis-py для подключения к серверу Redis и получения заданий из списка следующим образом:

from redis import Redis
r = Redis(host="hostname-of-machine-running-redis")
while r.llen('jobs:machine1'):
    job = r.lpop('commands:machine1')
    os.system('sh ' + job + ' &')

Конечно, вы можете с легкостью извлекать задания из очереди и выполнять их в Ruby:

require 'redis'
redis = Redis.new(:host => 'hostname-of-machine-running-redis')
while redis.llen('jobs:machine1')
    job = redis.lpop('commands:machine1')
    `sh #{job} &`
end

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

0 голосов
/ 22 января 2012

Попробуйте цикл while?Если это не сработает, на стороне Python попробуйте использовать оператор TRY, например, так:

...