Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Secure Programming for Li...6507 
 Linux Kernel 2.6...5279 
 Trees...1118 
 Максвелл 3...1050 
 William Gropp...986 
 Go Web ...961 
 Ethreal 3...929 
 Ethreal 4...915 
 Gary V.Vaughan-> Libtool...913 
 Ext4 FS...901 
 Clickhouse...900 
 Rodriguez 6...899 
 Ethreal 1...896 
 Steve Pate 1...884 
 C++ Patterns 3...860 
 Assembler...853 
 Ulrich Drepper...844 
 DevFS...786 
 MySQL & PosgreSQL...771 
 Стивенс 9...756 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org

Распределенные вычисления в питоне

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

Тестировать вы сможете на локальной машине, но лучше иметь хотя бы одну удаленную машину, доступ к которой возможен по протоколу ssh. Если у вас есть такая удаленная машина, для удобства и автоматизации процесса кластеризации вам понадобится доступ на эту машину по протоколу ssh без пароля. Для этого вам нужно сгенерировать публичные ключи, которые обычно лежат в домашней папке пользователя в подкаталоге .ssh, после чего скопировать эти ключи на удаленную машину в аналогичный каталог. Для генерации ключей выполните на своей локальной машине команду:

ssh-keygen -trsa

После чего зайдите в свой подкаталог .ssh и скопируйте два файла - id_rsa.pub и authorized_keys - на удаленную машину.

Начнем мы с библиотеки:

DistributedPython

Скачать можно тут.
Распределенный софт зачастую использует на самом нижнем уровне команду "ssh где-то сделать-что-то". Эта библиотека использует питоновские системные модули multiprocessing и subprocess для формирования очереди задач и управления этими задачами на удаленных хостах. Вы просто формируете обычный список команд и запускаете их в параллельном режиме. Под командами здесь понимаются обычные юниксовые команды, выполняемые из командной строки. Например, если нам нужно узнать системную дату на каком-то удаленном компьютере, вы просто в терминале набираете команду "ssh computer.at.your.domain date". Для нашего случая это будет означать, что в списке будет 'date'.

В этой библиотеке всего несколько файлов:

testSubmitMaster.py - исполняемый скрипт верхнего уровня, включающий в себя тот самый список команд. Он при своем выполнении будет генерировать логи в виде outputX.dat.

testScript - это shell-скрипт, который используется testSubmitMaster.py. Он содержит несколько переменных - id-шник процесса, имя хоста, время.

submitMaster.py - включает две функции - processCommandsInParallel и submitMaster.
Функция processCommandsInParallel вызывается из testSubmitMaster.py и делает следующее:
1. Создает процесс submitMaster
2. Назначает команды для submitMaster
3. Ожидает окончания работы submitMaster.
Коннект между submitMaster и функцией осуществляется с помощью канала Pipe, создается JobDistributor и очередь queue. В цикле:
прослушиваются каналы
проверяется очередь, если она освобождается, назначаются новые задачи

jobDistributor.py - класс содержит список доступных машин и назначает им задачи. Создается один инстанс JobDistributor. Он использует subprocess, с помощью которого создает новый процесс (Popen) для выполнения команды ssh. Информация о процессе хранится в обьекте Job, JobDistributor формирует словарь, в котором ключ - это имя хоста, а значение обьект Job. Этот скрипт нужно запустить отдельно.

listQueue.py - класс, отвечающий за работу очереди задач.






Batchlib

Эта питоновская библиотека предоставляет интерфейс для выделения достурных машин в сети. назначает им вычислительные задачи и собирает результаты. Его можно загрузить по адресу Batchlib. Его также можно загрузить у меня. Для выполнения скрипта на удаленной машине Batchlib в свою очередь использует другой питоновский пакет - exec_proxy, который можно также скачать тут. exec_proxy позволяет работать по протоколу ftp, дает возможность использовать команды системного питоновского модуля os. Этот модуль можно использовать не только в параллельных вычислениях, но и вообще в обыденной жизни, например для администрирования удаленных машин.

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

 
 connection_program -  "ssh -x" (по умолчанию)
 remote_program - по умолчанию это полный путь к скрипту remote.py на удаленной машине
 
 
Класс Exec_proxy этого модуля имеет параметр - хост. У этого класса есть много доступных методов, которые выполняют различные действия на удаленной машине либо обрабатываюn ошибки, например:
 
 newdir() - создает временную директорию для хранения файлов
 mkdir() - создает новый каталог на удаленной машине
 chdir()
 rmdir()
 getcwd()
 isdir()
 isfile()
 exists()
 listdir()
 chmod()
 stat()
 mkfifo() - создает именованный канал на удаленной машине
 symlink()
 unlink() - удаляет файл
 upload() - загружает файл с локальной на удаленную машину
 download() - загружает файл судаленной на локальную машину
 write() - создает файл
 read()
 run() - выполняет команду, которая выступает в качестве параметра 
 
 
Ошибки обрабатываются с помощью следующих методов:
 
 is_ok() - возвращает 1 в случае ошибки
 get_error() - возвращает саму ошибку
 reset_error() - 
 
 
Следующий простой пример показывает, как можно вызвать скрипт на удаленной машине. Предварительно нужно скопировать remote.py, который вы сможете найти в пакете, на удаленную машину и проверить, что на ней доступен питон, а также 22-й порт по протоколу ssh.
 import exec_proxy
 import os,stat
 
 exec_proxy.remote_program=os.path.join(os.getcwd(),'.','remote.py')
 ep=exec_proxy.Exec_proxy('user@remote_host')
 print ep.listdir('./');
 
Скрипт должен вывести содержимое корневого каталога текущего пользователя на удаленной машине.






dispy

Следующая библиотека, которую мы рассмотрим - dispy. Официальный сайт - http://dispy.sourceforge.net/. Его также можно скачать у меня.

Этот модуль можно использовать на локальной много-процессорной машине(SMP), а также в кластере. Хорошо подходит для распараллеленных вычислений, где вычислительные задачи не связаны между собой. Dispy использует asyncoro - фреймворк, построенный на асинхронных сообщениях, использующий неблокирующие сокеты, epoll, Поддерживается передача вычислений, файлов, сообщений. В качестве вычислений могут выступать как функции, так и отдельные программы. Ноды могут располагаться как в локальной сети, так и в удаленной, в последнем случае можно использовать ssh. Ноды можно открывать динамически: в модуле есть шедулер, который контролирует работу нод в кластере и может перераспределять задания. Доступен механизм callback. Установить dispy можно, скачав пакет исходников, либо с помощью команды pip3 install dispy.

Dispy состоит из 4 основных компонентов или собственно модулей :
1. dispy.py - базовая библиотека классов для cоздания кластеров. Есть 2 механизма создания кластеров - JobCluster либо SharedJobCluster. В первом случае используется встроенный шедулер, во втором случае должен быть создан отдельный шедулер с помощью другого модуля - dispyscheduler.py

2. dispynode.py - устанавливается на каждой кластерной ноде и выполняет там всю работу

3. dispyscheduler.py - шедулер, который может управлять работой нод самостоятельно.

4. dispynetrelay.py - нужен в случае использования сложной сетевой конфигурации. Если все ноды кластера перчислены в качестве параметра на этапе его создания, этот модуль не нужен. Он может получать информацию о дополнительных нодах в процессе работы.

Теперь рассмотрим простой пример. Создадим на локальной машине кластер из 5 нод, каждая из которых будет выполнять одну и ту же функцию compute. Под локальной нодой мы понимаем отдельный питоновский процесс. Каждой ноде будет передаваться случайное число в диапазоне от 1 до 10 секунд, в течение которых каждая нода будет находиться в паузе, после чего каждая нода будет возвращать собственный id-шник. В конце основной сценарий будет распечатывать протокол ответов. Основной сценарий.

 def compute(n):
     import time, socket
     time.sleep(n)
     host = socket.gethostname()
     return (host, n)
 
 if __name__ == '__main__':
     import dispy, random
     cluster = dispy.JobCluster(compute, nodes=['localhost'])
     jobs = []
     for n in range(5):
         job = cluster.submit(random.randint(1,10))
         job.id = n
         jobs.append(job)
     # cluster.wait()
     for job in jobs:
         host, n = job()
         print '%s executed job %s at %s with %s' % (host, job.id, job.start_time, n)
     cluster.stats()
 
Перед тем, как запустить основной сценарий, нужно сначала локально запустить следующую команду:

dispynode.py -d -i localhost

После этого запускаем основной сценарий, который выведет что-то типа:

 localhost executed job 0 at 1414068881.77 with 19
 localhost executed job 1 at 1414068881.77 with 12
 localhost executed job 2 at 1414068893.8 with 20
 localhost executed job 3 at 1414068900.81 with 11
 localhost executed job 4 at 1414068911.84 with 18
 ()
                            Node |  CPUs |    Jobs |    Sec/Job | Node Time Sec
 ------------------------------------------------------------------------------
  127.0.0.1 (localhost)          |     2 |       5 |     16.020 |        80.100
 
 






Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье