2012-04-04 3 views

ответ

58

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

Напротив, неблокирующая связь осуществляется с использованием MPI_Isend() и MPI_Irecv(). Эти функции немедленно возвращаются (т. Е. Не блокируются), даже если связь еще не завершена. Вы должны позвонить MPI_Wait() или MPI_Test(), чтобы узнать, закончилась ли связь.

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

Обратите внимание, что коллективное сообщение (например, все-сокращение) доступно только в его блокирующей версии до MPIv2. IIRC, MPIv3 вводит неблокирующую коллективную связь.

Краткий обзор режимов отправки MPI можно увидеть here.

+1

так что MPI_Send() совпадает с MPI_Isend() + MPI_Wait()? – lamba

+0

Да, кроме накладных расходов, вы можете думать о MPI_Send() как MPI_Isend(), за которым следует MPI_Wait(). – user1202136

+11

@ user1202136: Возможно, вы захотите упомянуть, что 'MPI_Send' завершается, когда вы можете повторно использовать буфер, независимо от того, получил ли приемник данные (или даже от того, были ли данные отправлены вообще). –

8

При использовании блокировки связи вы должны быть заботиться о передачи и приема вызовов на примере взгляд на этот код

if(rank==0) 
{ 
    MPI_Send(x to process 1) 
    MPI_Recv(y from process 1) 
} 
if(rank==1) 
{ 
    MPI_Send(y to process 0); 
    MPI_Recv(x from process 0); 
} 

Что происходит в этом случае?

  1. Процесс 0 отправляет x для обработки 1 и блокирует до тех пор, пока процесс 1 не получит x.
  2. Процесс 1 отправляет y для обработки 0 и блокирует до тех пор, пока процесс 0 не получит y, но
  3. Процесс 0 блокируется таким образом, что процесс 1 блокирует бесконечность до тех пор, пока оба процесса не будут убиты.
+4

Я так и думал. Но когда я использую MPI_Send на своем компьютере, я считаю, что проблема внутри может быть сложнее. Вышеприведенный код работает, поскольку он может перемещать сообщение в буфер. Только 'MPI_Ssend' строго * блокирует *, так как он возвращается, пока получатель не получит сообщение. Следующие ссылки объясняют, что разные поставщики выбирают другую реализацию. http://www.mcs.anl.gov/research/projects/mpi/sendmode.html –

3

Это очень просто.

Неблокирующие средства вычисление и передача данных могут происходить в одно и то же время для одного процесса.

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

+0

его круто спасибо @Pab Peter –

3

Это сообщение, хотя оно немного устарело, но я утверждаю принятый ответ. утверждение «Эти функции не возвращаются до тех пор, пока сообщение не будет завершено» немного ошибочно, поскольку блокировка связи не гарантирует никакого рукопожатия b/w операций отправки и получения.

Во-первых, необходимо знать, посыла имеет четыре режима связи: Standard, буферизацией, Синхронный и Готовые и каждый из них может быть блокировки и неблокирующая

В отличие от отправки, принимает только один режим и может быть блокировка или неблокирование.

BLOCKING COMMUNICATION: Блокировка не означает, что сообщение было доставлено в приемник/получатель. Это просто означает, что буфер (посылать или получать) доступен для повторного использования. Чтобы повторно использовать буфер, достаточно скопировать информацию в другую область памяти, то есть библиотека может скопировать данные буфера в собственное место памяти в библиотеке, а затем, скажем, например, вернуть MPI_Send.

Стандарт MPI позволяет очень четко отделить буферизацию сообщений от операций отправки и получения. Блокировка отправки может быть завершена, как только сообщение будет буферизовано, хотя не было отправлено сопоставление. Но в некоторых случаях буферизация сообщений может быть дорогостоящей, и поэтому непосредственное копирование из буфера отправки в буфер приема может быть эффективным. Следовательно, MPI Standard предоставляет четыре разных режима отправки, чтобы дать пользователю свободу выбора соответствующего режима отправки для ее приложения. Давайте посмотрим на то, что происходит в каждом режиме связи:

1. Стандартный режим

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

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

Синтаксис для стандартной отправки ниже:

int MPI_Send(const void *buf, int count, MPI_Datatype datatype, 
      int dest, int tag, MPI_Comm comm) 

2. Режим буферизации

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

Синтаксис для буфера отправки:

int MPI_Bsend(const void *buf, int count, MPI_Datatype datatype, 
      int dest, int tag, MPI_Comm comm) 

3. Синхронный режим

В синхронном режиме отправки, отправки может быть запущен ли или не совпадающий отправил получать. Однако отправка будет завершена успешно только в том случае, если соответствующий прием был отправлен, и приемник начал получать сообщение, отправленное синхронной отправкой. Завершение синхронной отправки не только указывает, что буфер в передаче может быть повторно использован, но также и тот факт, что процесс приема начал получать данные. Если блокируются как отправка, так и прием, связь не завершается с обоих концов до того, как произойдет сближение с передающим процессором.

Синтаксис для синхронной отправки:

int MPI_Ssend(const void *buf, int count, MPI_Datatype datatype, int dest, 
       int tag, MPI_Comm comm) 

4. Режим готовности

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

Синтаксис для готового отправить:

int MPI_Rsend(const void *buf, int count, MPI_Datatype datatype, int dest, 
       int tag, MPI_Comm comm) 

К счастью MPI решил держать вещи вспомогательный шпур для пользователей с точки зрения получения и есть только один получит в блокировании связи: MPI_Recv, и может быть использован с любым из четырех режимов отправки, описанных выше. Для MPI_Recv, средство блокировки, которое получает возврат только после того, как оно содержит данные в его буфере. Это означает, что получение может завершиться только после того, как начата соответствующая отправка, но не подразумевает, может ли она быть выполнена до того, как будет завершена соответствующая отправка.

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

неблокируемых СВЯЗИ: Для Неблокирующих коммуникаций, приложение создает запрос для связи для передачи и/или приема и получает обратно ручку, а затем завершает работу. Это все, что необходимо для гарантии выполнения процесса. I. В библиотеке MPI сообщается, что операция должна быть выполнена.

Для стороны отправителя это позволяет перекрывать вычисления с помощью связи.

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

Смежные вопросы