Возможно, самым элегантным решением было бы сделать код 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_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. Вам также потребуется использовать одну из доступных привязок Python MPI.
Обратите внимание, что вам нужно только добавить некоторые вызовы MPI в ваш скрипт Python, такие как MPI_Init
, MPI_Finalize
, MPI_Comm_split
и соответствующие MPI_Send
/MPI_Recv
. Параллельно делать не надо. MPI довольно универсален, что позволяет использовать его не только для параллельной совместной работы, но и в качестве общей среды обмена сообщениями. Но обратите внимание, что привязки Python должны использовать ту же библиотеку MPI, что и остальная часть программы.
Другим решением было бы использование некоторой библиотеки очередей сообщений или пула файлов (что на самом деле является грубой реализацией MQ).
person
Hristo Iliev
schedule
15.05.2012