Начиная с версии 3 стандарта, MPI позволяет удалять совпадающие сообщения из очереди сообщений, чтобы они больше не были видны последующим запросам/получениям. Это делается с помощью так называемых совпадающих зондов. Просто замените MPI_Iprobe
на MPI_Improbe
, что является неблокирующей операцией сопоставленного зонда:
int flag;
MPI_Status status;
MPI_Message msg;
MPI_Improbe(source, tag, comm, &flag, &msg, &status);
Как только MPI_Improbe
возвращает 1 в flag
, приходит сообщение, соответствующее (source, tag, comm)
. Дескриптор сообщения сохраняется в msg
, и сообщение удаляется из очереди. Последующие запросы или приемы с совпадающим триплетом (источник, тег, связь) — в том же потоке или в другом — не увидят это же сообщение снова и, следовательно, не будут мешать его приему потоком, который совпал с ним изначально.
Чтобы получить соответствующее сообщение, используйте MPI_Imrecv
(или блокировку MPI_Mrecv
):
MPI_Request req;
MPI_Imrecv(buffer, count, dtype, &msg, &req);
do
{
...
MPI_Test(&req, &flag, &status);
}
while (!flag);
Версии MPI до 3.0 не предоставляют подобных функций. Но, если я вас правильно понял, вам нужно только гарантировать, что ни один соответствующий зонд не будет отправлен до того, как MPI_Irecv
получит возможность удалить сообщение из очереди (что и предназначено для предотвращения совпадающего зонда + получения). Если вы исследуете основной поток, а затем отправляете сообщения в разные потоки, вы можете использовать семафор, чтобы отложить выполнение следующего зонда основным потоком до тех пор, пока рабочий не выдаст MPI_Irecv
. Если у вас есть несколько потоков, выполняющих probe+receive, вы можете просто выполнить вызов MPI_Irecv
в том же критическом разделе (или любом другом примитиве синхронизации, который вы используете для сериализации вызовов MPI в соответствии с требованиями MPI_THREAD_SERIALIZED
) как MPI_Iprobe
после того, как проверка завершится. успешный:
// Worker thread
CRITICAL(mpi)
{
MPI_Iprobe(source, tag, comm, &flag, &status);
if (flag)
MPI_Irecv(buffer, count, dtype, status.MPI_SOURCE, status.MPI_TAG, comm, &req);
}
Замените нотацию CRITICAL(name) { ... }
любыми примитивами, которые предоставляет ваша среда программирования.
person
Hristo Iliev
schedule
21.08.2015