блок буст-теста не может вызвать функцию mpi

Я внимательно осмотрелся вокруг, но не смог найти ссылки на эту проблему.

Я написал программу на C ++, которую я тестирую с помощью boost / unit. Серийная версия работает нормально, а модульный тест работает.
Теперь я сделал программу параллельной с помощью функции, выполняющей смущающе параллельную работу с MPI. Если записать мой собственный тест, вызывающий параллельную функцию — назовем это парафункцией — он работает хорошо, MPI работает нормально.
Компиляция выполняется с помощью mpic ++, и я использую mpixec для запуска программы.

Однако, если я вызываю функцию parafunction в тестовом буст-тесте, MPI работает неправильно, тест запускается несколько раз и происходит сбой процесса, когда несколько MPI::Init называются.
Вот пример ошибки, которую я получаю:

Функция MPI_comm_size () была вызвана после вызова MPI_FINALIZE.

Это запрещено стандартом MPI.

Ваша работа MPI теперь будет прервана.

Мой тестовый пример находится в test_unit, автоматически обрабатываемом master_test_suite. Как я уже сказал, без распараллеливания это работает на отлично.

Парафункция звонков MPI::Init а также MPI::Finalizeи никакая другая функция файлов не должна выполнять какие-либо вещи, связанные с MPI.

Кто-нибудь сталкивался с подобной проблемой раньше?

Мой тестовый прогон довольно длинный, поэтому я действительно мог бы использовать параллельную версию моей программы!

Спасибо за вашу помощь

1

Решение

Функция, которая как инициализирует, так и завершает, может быть вызвана только один раз, потому что MPI может быть инициализирован только один раз за время существования программы и может быть завершен только один раз. Чтобы предотвратить множественные вызовы инициализации, поместите вызов в MPI_Init() или же MPI_Init_thread() в условном:

int already_initialised;

MPI_Initialized(&already_initialised);
if (!already_initialised)
MPI_Init(NULL, NULL);

Что касается финализации, она должна быть перемещена за пределы вашей функции, вероятно, в atexit(3) обработчик, если вы не хотите загрязнять внешнюю область вызовами MPI. Например:

void finalise_mpi(void)
{
int already_finalised;

MPI_Finalized(&already_finalised);
if (!already_finalised)
MPI_Finalize();
}

...
atexit(finalise_mpi);
...

atexit() вызов может быть частью кода инициализации, например:

int already_initialised;

MPI_Initialized(&already_initialised);
if (!already_initialised)
{
MPI_Init(NULL, NULL);
atexit(finalise_mpi);
}

Это не будет устанавливать atexit(3) обработчик, если MPI уже был инициализирован. Основная идея заключается в том, что если MPI был инициализирован при входе в функцию, это будет означать, что MPI_Init() был вызван во внешнем объеме, и можно было бы ожидать, что MPI_Finalize() там тоже называется.

На вашем месте я бы переместил инициализацию и финализацию MPI из функции параллельной обработки. Правильная последовательность вызова будет инициализировать MPI, запустить тесты, а затем завершить MPI.

Я использовал привязки C в вышеприведенном тексте, поскольку привязки C ++ были устаревшими в MPI-2.2, а затем удалены в MPI-3.0.

2

Другие решения

Других решений пока нет …