boost :: mpi генерирует MPI_ERR_TRUNCATE для нескольких передач isend / irecv с одним и тем же тегом

0

Я вижу ошибку MPI_ERR_TRUNCATE с boost::mpi при выполнении нескольких передач isend/irecv с тем же тегом с использованием сериализованных данных. Это не параллельные передачи, т.е. Не задействована нить. В то же время существует более одной передачи. Вот небольшая тестовая программа, которая демонстрирует неудачу:

#include <iostream>
#include <string>
#include <vector>
#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>

static const size_t N = 2;

int main() {
   boost::mpi::environment env;
   boost::mpi::communicator world;

#if 1
   // Serialized types fail.
   typedef std::string DataType;
#define SEND_VALUE "how now brown cow"
#else
   // Native MPI types succeed.
   typedef int DataType;
#define SEND_VALUE 42
#endif

   DataType out(SEND_VALUE);
   std::vector<DataType> in(N);
   std::vector<boost::mpi::request> sends;
   std::vector<boost::mpi::request> recvs;
   sends.reserve(N);
   recvs.reserve(N);

   std::cout << "Multiple transfers with different tags\n";
   sends.clear();
   recvs.clear();
   for (size_t i = 0; i < N; ++i) {
      sends.push_back(world.isend(0, i, out));
      recvs.push_back(world.irecv(0, i, in[i]));
   }
   boost::mpi::wait_all(sends.begin(), sends.end());
   boost::mpi::wait_all(recvs.begin(), recvs.end());

   std::cout << "Multiple transfers with same tags\n";
   sends.clear();
   recvs.clear();
   for (size_t i = 0; i < N; ++i) {
      sends.push_back(world.isend(0, 0, out));
      recvs.push_back(world.irecv(0, 0, in[i]));
   }
   boost::mpi::wait_all(sends.begin(), sends.end());
   boost::mpi::wait_all(recvs.begin(), recvs.end());

   return 0;
}

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

libС++ abi.dylib: завершение с неперехваченным исключением типа boost :: exception_detail :: clone_impl>: MPI_Unpack: MPI_ERR_TRUNCATE: сообщение усечено

Если я использую собственный тип данных MPI, чтобы сериализация не вызывалась, все работает. Я получаю ту же ошибку на MacPorts, увеличивая 1,55 с помощью OpenMPI 1.7.3, а Debian - 1.49 с OpenMPI 1.4.5. Я попробовал несколько передач с тем же тегом непосредственно с интерфейсом API C и, похоже, работал, хотя, конечно, я могу передавать только собственные типы данных MPI.

Мой вопрос заключается в том, является ли наличие нескольких выдающихся переводов на одном и том же теге действительной операцией с boost::mpi, и если это так, то есть ошибка в моей программе или ошибка в boost::mpi?

Теги:
mpi
boost
boost-mpl

2 ответа

4
Лучший ответ

В текущей версии boost, 1.55, boost::mpi не гарантирует не обгоняющих сообщений. Это в отличие от базового API MPI, который выполняет:

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

Причина boost::mpi не гарантирует без обгона, что сериализованные типы данных передаются в двух сообщениях MPI, один для размера и один для полезной нагрузки, а irecv для второго сообщения не может быть отправлен до тех пор, пока не будет проверено первое сообщение.

Рассматривается предложение об обеспечении без обгона в boost::mpi. Дальнейшее обсуждение можно найти в списке рассылки boost::mpi начинающемся здесь.

0

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

Способ, которым MPI обычно обрабатывает отправку сообщения, заключается в том, что при вызове send он будет возвращаться после вызова, как только сообщение будет обработано библиотекой. Это может привести к тому, что сообщение было скопировано во внутренний буфер или что сообщение было фактически передано удаленному процессу и получено. В любом случае сообщение должно куда-то идти. Если у вас уже нет ожидающего буфера приема, сообщение должно быть буферизировано внутри. В конце концов, реализация закончится из этих буферов и начнет делать плохие вещи (например, возвратить ошибки пользователю), которые вы, вероятно, видите здесь.

Решение заключается в предварительной отправке буферов приема. В вашем случае вы можете просто нажать все isend и irecv в один и тот же вектор и позволить MPI обрабатывать все. Это даст MPI доступ ко всем буферам приема, чтобы ваши сообщения могли куда-то идти.

  • 0
    Спасибо за ваш ответ, но это не так. Порядок, в котором отправляются и отправляются сообщения, не меняет поведение теста. И поведение также то же самое, если я только жду на recvs, а не на посылках вообще. Что касается буферизации, обратите внимание, что я isend() и irecv() которые не используют буферизацию MPI (любая буферизация выполняется в boost::mpi ).
  • 0
    Он явно не использует буферизацию, но реализация MPI использует буферизацию. Вы пытались поместить оба отправителя и получателя в один и тот же вектор?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню