Взаимодействайте с MPI двоичен файл чрез (не-MPI) python скрипт

Бих искал по някакъв начин да задействам изпълнението на определени функции на MPI програма (написана на C++) чрез, например, (сериен) скрипт на Python. Този скрипт на Python трябва да стартира програмата mpi в началото с, напр.

subprocess.call(['mpirun','-np', '4', 'mpibinary', 'args' ])

Трябва да извикам функция на тази MPI програма няколко пъти и искам да избегна рестартирането на програмата за различни входове, тъй като трябва да инициализирам отново всички мои структури от данни, което е скъпо. Затова помислих за външно задействане на функция, когато MPI програмата е неактивна. Мисля, че това може да се направи с файлов IO, т.е. основният ранг на програмата MPI наблюдава определен файл в цикъл while(1) и веднага щом съдържанието му се промени, той анализира новото съдържание, уведомява другите рангове и извиква функция . Има ли по-елегантно решение на моя проблем?

Най-доброто решение би било да имам клас на python, който обгръща важните функции на C++ MPI програмата, така че да мога да ги извикам от python с

mpiprogram.superfunction(a,b)

person thisch    schedule 14.05.2012    source източник
comment
Вместо да наблюдавате файл за промени (което изглежда крехко), можете да използвате наименуван канал или сокет, за да изпращате команди до основния MPI ранг от Python.   -  person Greg Inozemtsev    schedule 15.05.2012
comment
Благодаря за отговора. Използването на сокети разбира се е по-„елегантно“ от гледането на файлове, но всички тези споменати решения изискват писане на много прокси мъничета. Все още търся нещо, което отнема по-малко време.   -  person thisch    schedule 15.05.2012


Отговори (1)


Може би най-елегантното решение би било да направите кода на Python част от вашето MPI приложение. След това ще може директно да изпраща данни (чрез MPI съобщения) до останалата част от MPI приложението, тъй като ще бъде част от него. Тук има два различни подхода:

1) Вмъкнете двоичния файл на Python като ранг 0 във вашата MPI работа. За да го изключите от участие в колективни операции в mpibinary, ще трябва да направите субкомуникатор, който изключва ранг 0 и да го използвате за цялата по-нататъшна колективна комуникация в mpibinary. Първата стъпка е лесната част. В Open MPI бихте направили:

mpirun --hostfile hosts -np 1 pythonbinary args : -np 32 mpibinary args

Това се нарича стартиране на MPMD (множество програми с множество данни) и ще стартира едно копие на pythonbinary, което ще стане ранг 0, а също и 32 копия на mpibinary, които ще станат ранг 1, ранг 2, ... до ранг 32 (33 процеса в обща сума). Други реализации на MPI също предоставят много подобни механизми за стартиране на MPMD. Тогава ще използвате MPI_Comm_split(), за да създадете нов комуникатор, който не включва програмата Python. Разделянето на комуникатор е колективна операция. Ето защо трябва да го извикате както във вашия Python код, така и във вашето C++ приложение. MPI_Comm_split() взема "цвят" и ключ и разделя комуникатора на множество подкомуникатори според различните цветове. След това процесите със същия цвят се сортират въз основа на стойността на ключа. Най-вероятно ще искате да го наречете така:

в Python:

python_comm = mpi.mpi_comm_split(mpi.MPI_COMM_WORLD, 0, 0)

in C++:

int rank;
MPI_Comm c_comm;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_split(MPI_COMM_WORLD, 1, rank, &c_comm);

Чрез използването на rank като ключ се гарантира, че редът на процесите в c_comm ще бъде същият, както беше преди разделянето, т.е. ранг 1 от MPI_COMM_WORLD ще стане ранг 0 в c_comm, ранг 2 ще стане ранг 1 и т.н.

Отсега нататък C++ приложението може да използва c_comm за извършване на колективни операции както обикновено. За да комуникирате между кода на Python и C++, все още трябва да използвате MPI_COMM_WORLD и кодът на Python все още ще бъде ранг 0 в него.

2) Използвайте средствата за управление на процеси MPI-2. Първо бихте изпълнили MPI задача, която се състои само от двоичния файл на Python:

mpirun --hostfile hosts -np 1 pythonbinary args

Тогава двоичният файл на Python ще създаде другия двоичен файл на MPI директно, използвайки MPI_Comm_spawn() с желания брой нови процеси. Новосъздадените процеси ще имат свои собствени MPI_COMM_WORLD и няма да е необходимо да използвате MPI_Comm_split(). Освен това операцията за създаване на хайвер ще създаде интеркомуникатор, който ще позволи на кода на Python да изпраща съобщения до другата част на приложението MPI.


И в двата случая файлът hosts ще съдържа дефиниция на всички хостове за изпълнение, които могат да изпълняват двоичните файлове на MPI. Ще трябва също да използвате едно от наличните MPI свързвания на Python.

Обърнете внимание, че трябва само да добавите някои MPI извиквания към вашия скрипт на Python като MPI_Init, MPI_Finalize, MPI_Comm_split и съответните MPI_Send/MPI_Recv. Не е необходимо да го правите успоредно. MPI е доста гъвкав, което ви позволява не само да го използвате за паралелно споделяне на работа, но и като обща рамка за съобщения. Но имайте предвид, че обвързванията на Python трябва да използват същата MPI библиотека като останалата част от програмата.

Друго решение би било да се използва някаква библиотека за опашка за съобщения или групиране на файлове (което наистина е грубо изпълнение на MQ).

person Hristo Iliev    schedule 15.05.2012
comment
1) означава ли, че трябва да модифицирам mpibinary? Кой трябва да извика MPI_Comm_split? - person thisch; 18.05.2012
comment
За съжаление да, както 1), така и 2) изискват леки модификации на вашия MPI двоичен файл. Подход 2) изисква по-малко модификации от 1). Разширих отговора, за да включва информация как да се обадя на MPI_Comm_split, тъй като ограничението за дължина на коментарите е твърде строго. - person Hristo Iliev; 18.05.2012