Отбрасывает ли MPI или задерживает сообщения?

Я задал тот же вопрос здесь, но Я думаю, что это было слишком долго, поэтому я попробую еще раз, но короче:

У меня есть программа на C++, использующая последнюю версию OpenMPI в кластере Rocks с настройкой master/slave. Подчиненные устройства выполняют задачу, а затем сообщают данные мастеру, используя блокирующие вызовы MPI_SEND / MPI_RECV (через Boost MPI), которые записывают данные в базу данных. Мастер в настоящее время значительно медленнее, чем ведомые. У меня проблемы с программой, потому что около половины подчиненных застревают на первой задаче и никогда не сообщают свои данные; используя strace/ltrace, кажется, что они застряли при опросе в MPI_SEND, и их сообщение никогда не было получено.

Я написал программу для проверки этой теории (опять же, перечисленные в полном объеме здесь), и я могу вызвать аналогичную проблему - обмен данными с подчиненными значительно замедляется, поэтому они выполняют меньше задач, чем должны, - путем манипулирования скоростью подчиненных и ведущих устройств, использующих сон. Когда скорость (мастер) > скорость (рабы), все работает нормально. Когда скорость (мастер) ‹ скорость (ведомые), сообщения для некоторых подчиненных каждый раз значительно задерживаются.

Любые идеи, почему это может быть?


person Winawer    schedule 20.10.2011    source источник
comment
Посмотрите здесь семантику MPI_Send/Recv: netlib. org/utk/papers/mpi-book/   -  person suszterpatt    schedule 20.10.2011
comment
Исходя из этого... может быть, я неправильно использую MPI_ANY_SOURCE? Сообщения, отправляемые некоторыми ведомыми устройствами (вероятно, в зависимости от реализации/настройки), перехватываются, потому что Recv соответствует ... более новым сообщениям?   -  person Winawer    schedule 20.10.2011
comment
возможный дубликат Почему некоторые из этих ведомых устройств MPI медленно сообщить?   -  person Ken White    schedule 21.10.2011
comment
@KenWhite Да, извините, это был преднамеренный дубликат с моей стороны. Они оба мой вопрос; Я просто подумал, что поток деталей в первом, возможно, отпугивал возможные ответы, поэтому я решил попробовать еще раз.   -  person Winawer    schedule 21.10.2011
comment
@Winawer: Я понимаю это - закрытие как дубликат автоматически добавляет возможное. :) Вам следует отредактировать исходный вопрос, чтобы уточнить/улучшить его, вместо того, чтобы публиковать отдельный дублирующий вопрос.   -  person Ken White    schedule 21.10.2011
comment
@KenWhite Спасибо, буду иметь в виду на будущее. Однако я не знаю, что с этим делать сейчас; ответ на этот вопрос может быть полезен другим, но он может не иметь смысла без контекста предыдущего. Должен ли я скопировать информацию из предыдущего вопроса в этот?   -  person Winawer    schedule 21.10.2011
comment
@Winawer: я не уверен. Я отмечу это модератору, чтобы он взглянул на него, и пусть он решит, как лучше с этим справиться. :)   -  person Ken White    schedule 21.10.2011


Ответы (1)


Насколько я вижу, это результат recv в цикле while на главном узле.

 ...
 while (1) {
 // Receive results from slave.
      stat = world.recv(MPI_ANY_SOURCE,MPI_ANY_TAG);
 ...

Когда есть сообщение от одного ведомого, мастер не может получить никаких сообщений, пока код внутри цикла while не завершится (что занимает некоторое время, так как есть сон), поскольку главный узел не работает параллельно. Поэтому все остальные ведомые устройства не могут начать отправку своих сообщений, пока первое ведомое устройство не закончит отправку своего сообщения. Затем следующее подчиненное устройство может начать отправку сообщения, но затем все остальные подчиненные устройства останавливаются до тех пор, пока не будет выполнен код внутри цикла while.

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

ОБНОВЛЕНИЕ 1:

Предположим, что мастер распространил свои данные. Теперь он ждет, пока рабы не отчитаются. Когда первый подчиненный ответит, он сначала отправит свой REPORTTAG, а затем свой DONETAG. Теперь мастер отправит ему обратно новую работу, если

 currentTask < numtasks

Теперь рабы снова начинают свой расчет. Возможно, сейчас дело обстоит так, что, пока он не закончил, хозяин мог обращаться только с другим рабом. Таким образом, подчиненный в начале теперь снова отправляет сначала свой REPORTTAG, а затем свой DONETAG и получает новую работу. Когда это продолжается, в конце концов, только 2 раба получили новую работу, а остальные не смогли закончить свою работу. Чтобы в какой-то момент это было правдой:

 currentTask >= numtasks

Теперь вы останавливаете все задания, даже если не все ведомые устройства вернули свои данные и выполнили более одной задачи.

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

В качестве решений я бы предложил:

  • Убедитесь, что все подчиненные завершены, прежде чем убивать все задания.
  • Используйте сбор и разброс вместо сообщений, тогда все подчиненные синхронизируются после каждой задачи.
  • Используйте буферизованные или небуферизованные операции отправки и получения, если сообщения не слишком большие. Убедитесь, что у вас не было переполнения памяти на Мастере
  • Измените режим Master/Slave на более параллельный рабочий режим, например, разделите все задачи на два узла, затем разделите задачи дальше от этих узлов на следующие два и так далее. В конце отправьте задачу обратно. Это решение также может иметь то преимущество, что стоимость связи составляет всего O(logn), а не O(n).

Надеюсь, это помогло.

person tune2fs    schedule 20.10.2011
comment
Но если бы все сообщения поступали последовательно, просто медленно, потому что они ожидают от ведущего, я бы ожидал, что работа займет много времени, но каждый ведомый будет выполнять одинаковое количество задач... верно? Если да, то почему их нет? Если нет, то что не так с моим мышлением? Только некоторые подчиненные устройства замедляются, а не все. А в полном коде некоторые ведомые устройства полностью застревают, и их сообщения никогда не приходят, независимо от того, как долго они ждут. - person Winawer; 20.10.2011
comment
Возможно, проблема в последнем else { в цикле while. Там вы пытаетесь отправить новую работу подчиненным: world.send(stat.source(),TASKTAG); world.send(stat.source(),TASKDATATAG,randnum); - person tune2fs; 20.10.2011
comment
На самом деле это похоже на то, что вы здесь описываете, хотя кажется, что проблема в MPI_ANY_SOURCE. Когда я изменяю этот ANY_SOURCE на цикл, который циклически проходит через ведомое устройство, последовательно собирая результаты, проблема исчезает, и код работает так, как я ожидал. Однако, если кто-то не может добавить что-то блестящее, я приму ваш ответ, потому что он заставил меня думать в правильном направлении. Спасибо! - person Winawer; 21.10.2011
comment
Если вы используете не использовать MPI_ANY_SOURCE, вы также будете синхронизировать ведомые устройства перед отправкой им новых задач. - person tune2fs; 21.10.2011