Насколько я вижу, это результат recv в цикле while в главном узле.
...
while (1) {
// Receive results from slave.
stat = world.recv(MPI_ANY_SOURCE,MPI_ANY_TAG);
...
Когда есть сообщение от одного ведомого, мастер не может получить никаких сообщений до тех пор, пока не завершится код внутри, пока цикл не завершится (что занимает некоторое время, пока идет спящий режим), так как мастер-узел не работаетпараллельно.Поэтому все другие ведомые не могут начать отправлять свои сообщения, пока первый ведомый не завершит отправку своего сообщения.Затем следующий подчиненный может начать отправку сообщения, но затем все остальные подчиненные останавливаются до тех пор, пока не будет выполнен код внутри цикла while.
Это приводит к тому, что поведение подчиненных очень медленное.Чтобы избежать этой проблемы, вам необходимо реализовать двухблоковую связь без блокировки или использовать глобальную связь.
ОБНОВЛЕНИЕ 1:
Предположим, что мастер распространил свои данные.Теперь он ждет, пока рабы не доложат.Когда первый раб отчитывается, он сначала отправит свой REPORTTAG, а затем свой DONETAG.Теперь мастер отправит ему обратно новую работу, если
currentTask < numtasks
Теперь рабы снова начнут с его расчета.Вполне возможно, что до тех пор, пока он не закончил, мастер мог обращаться только с другим рабом.Итак, раб начала теперь снова посылает сначала свой REPORTTAG, а затем DONETAG и получает новую работу.Когда это продолжается в конце, только 2 раба получили новые рабочие места, а остальные не смогли завершить свою работу.Так что в какой-то момент это так:
currentTask >= numtasks
Теперь вы останавливаете все задания, даже если не все подчиненные устройства отчитались и выполнили более одной задачи.
Эта проблема возникает чаще всего.когда сетевое соединение разных узлов сильно отличается.Причина заключается в том, что отправка и получение не обрабатываются после их вызова, вместо этого происходит обмен данными, если две из этих функций способны выполнить какое-то рукопожатие.
В качестве решения я бы предложил:
- Перед завершением всех заданий убедитесь, что все подчиненные устройства завершены
- Используйте сбор и разброс вместо сообщений, а затем всех подчиненных.синхронизируется после каждой задачи.
- Используйте буферизованные или небуферизованные операции отправки и получения, если сообщения не слишком большие.Убедитесь, что вы не получили переполнение памяти на Master
- . Перейдите с Master / Slave на более параллельный рабочий модуль, например, разделите все задачи на два узла, затем разделите задачи дальше от этих узлов на следующие два., и так далее.В конце концов отправьте задание обратно.Это решение может также иметь преимущество в том, что стоимость связи составляет только O (logn) вместо O (n).
Надеюсь, это помогло.