2012-04-04 19 views
43

Tengo problemas para entender el concepto de bloqueo de comunicación y comunicación sin bloqueo en MPI. ¿Cuáles son las diferencias entre los dos? ¿Cuáles son las ventajas y desventajas?mpi: bloqueo vs no bloqueo

Gracias!

Respuesta

58

La comunicación de bloqueo se realiza utilizando MPI_Send() y MPI_Recv(). Estas funciones no regresan (es decir, bloquean) hasta que la comunicación finaliza. Simplificando un poco, esto significa que el buffer pasado a MPI_Send() se puede reutilizar, ya sea porque MPI lo guardó en algún lugar o porque el destino lo recibió. Del mismo modo, MPI_Recv() se devuelve cuando el búfer de recepción se ha llenado con datos válidos.

En contraste, la comunicación sin bloqueo se realiza usando MPI_Isend() y MPI_Irecv(). Estas funciones regresan inmediatamente (es decir, no bloquean) incluso si la comunicación aún no ha finalizado. Debe llamar al MPI_Wait() o MPI_Test() para ver si la comunicación ha finalizado.

La comunicación de bloqueo se utiliza cuando es suficiente, ya que es algo más fácil de usar. La comunicación sin bloqueo se usa cuando es necesario, por ejemplo, puede llamar al MPI_Isend(), hacer algunos cálculos, luego hacer MPI_Wait(). Esto permite que los cálculos y la comunicación se superpongan, lo que generalmente conduce a un mejor rendimiento.

Tenga en cuenta que la comunicación colectiva (por ejemplo, all-reducir) solo está disponible en su versión de bloqueo hasta MPIv2. IIRC, MPIv3 introduce comunicación colectiva no bloqueante.

Se puede ver una vista general rápida de los modos de envío de MPI here.

+1

entonces un MPI_Send() es lo mismo que MPI_Isend() + MPI_Wait()? – lamba

+0

Sí, excepto por encima, puede pensar en MPI_Send() como MPI_Isend() seguido de MPI_Wait(). – user1202136

+11

@ user1202136: Es posible que desee mencionar que 'MPI_Send' se completa cuando puede reutilizar el búfer, independientemente de si el receptor ha recibido los datos (o incluso si los datos se han enviado aún). –

8

En el uso de la comunicación bloqueo debe ser cuidado acerca de enviar y recibir llamadas, por ejemplo vistazo a este código

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); 
} 

Lo que sucede en este caso?

  1. El proceso 0 envía x al proceso 1 y bloquea hasta que el proceso 1 reciba x.
  2. El proceso 1 envía y a procesar 0 y bloques hasta que el proceso 0 recibe y, pero
  3. proceso 0 está bloqueado de modo que el proceso 1 bloques para infinito hasta que se eliminen los dos procesos.
+4

Yo solía pensar que sí. Pero cuando uso MPI_Send en mi computadora, encuentro que el problema interno puede ser más complicado. El código anterior funciona, ya que podría mover el mensaje al búfer. Solo 'MPI_Ssend' es estrictamente * bloqueante *, ya que regresa hasta que el destino recibe el mensaje. Los siguientes enlaces explican que diferentes proveedores eligen una implementación diferente. http://www.mcs.anl.gov/research/projects/mpi/sendmode.html –

3

Es fácil.

Sin bloqueo significa que el cálculo y la transferencia de datos pueden ocurrir al mismo tiempo para un único proceso.

Mientras que Bloquear significa, oye amigo, debes asegurarte de que ya has terminado de transferir los datos y luego volver para terminar el próximo comando, lo que significa que si hay una transferencia seguida de un cálculo, el cálculo debe ser posterior al éxito. de transferencia.

+0

es genial gracias @Pab Peter –

3

Esta publicación, aunque es un poco antigua, pero contengo la respuesta aceptada. la declaración "Estas funciones no vuelven hasta que la comunicación haya finalizado" es un poco erróneo porque el bloqueo de las comunicaciones no garantiza ningún apretón de manos por las operaciones de envío y recepción.

En primer lugar es necesario saber, envío tiene cuatro modos de de la comunicación: estándar, con búfer, síncrono y Listo y cada uno de ellos puede ser bloqueo y no bloqueante

A diferencia de en enviar, recibir tiene solo un modo y puede ser bloqueando o sin bloqueo.

COMUNICACIÓN DE BLOQUEO: El bloqueo no significa que el mensaje se entregó al receptor/destino. Simplemente significa que el búfer (enviar o recibir) está disponible para su reutilización. Para reutilizar el búfer, es suficiente copiar la información a otra área de memoria, es decir, la biblioteca puede copiar los datos del búfer a la ubicación de la memoria propia en la biblioteca y, por ejemplo, por ejemplo, puede devolver MPI_Send.

El estándar MPI hace que sea muy claro desacoplar el búfer de mensaje de las operaciones de envío y recepción. Un envío de bloqueo se puede completar tan pronto como se haya almacenado el mensaje en el buzón, aunque no se haya publicado ninguna recepción coincidente. Pero en algunos casos, el almacenamiento en memoria intermedia de mensajes puede ser costoso y, por lo tanto, la copia directa desde el búfer de envío al búfer de recepción puede ser eficiente. Por lo tanto, el estándar MPI proporciona cuatro modos de envío diferentes para darle al usuario cierta libertad para seleccionar el modo de envío apropiado para su aplicación. Vamos a echar un vistazo a lo que sucede en cada modo de comunicación:

1. Modo Estándar

En el modo estándar, que depende de la Biblioteca MPI, sea o no para amortiguar el mensaje de salida . En el caso en que la biblioteca decida almacenar en búfer el mensaje saliente, el envío puede completarse incluso antes de que se haya invocado la recepción coincidente. En el caso en que la biblioteca decida no almacenar en búfer (por razones de rendimiento, o por falta de espacio en el búfer), el envío no volverá hasta que se haya publicado una recepción coincidente y los datos en el búfer de envío se hayan movido al búfer de recepción.

Así MPI_Send en el modo estándar es no local en el sentido de que enviar en modo estándar se puede iniciar o no una coincidencia reciben ha sido publicado y su finalización con éxito puede depender de la aparición de una coincidencia de recibir (debido al hecho de que depende de la implementación si el mensaje será almacenado o no).

La sintaxis de envío estándar es a continuación:

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

2. Modo tamponada

Al igual que en el modo estándar, el envío en el modo de buffer se puede iniciar con independencia del hecho de que una coincidencia recibir ha sido publicado y el envío puede completarse antes de que se haya publicado una recepción coincidente. Sin embargo, la diferencia principal surge del hecho de que si el envío se mira y no se publica una recepción coincidente, el mensaje saliente debe ser almacenado. Tenga en cuenta que si se envía la recepción coincidente, el envío en búfer puede reunirse felizmente con el procesador que inició la recepción, pero en caso de que no haya recepción, el envío en modo de búfer debe almacenar el mensaje saliente para permitir que se complete el envío.En su totalidad, un envío en memoria intermedia es local. La asignación de búfer en este caso está definida por el usuario y en el caso de que no haya suficiente espacio en el búfer, se produce un error.

Sintaxis para búfer de emisión:

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

3. Modo síncrono

En modo de envío síncrono, envíe se puede iniciar o no una coincidencia tuvo lugar la recepción publicada. Sin embargo, el envío se completará satisfactoriamente solo si se ha publicado una recepción coincidente y el receptor ha comenzado a recibir el mensaje enviado por el envío síncrono. La finalización del envío síncrono no solo indica que el búfer en el envío puede reutilizarse, sino también el hecho de que el proceso de recepción ha comenzado a recibir los datos. Si tanto el envío como la recepción se bloquean, la comunicación no se completa en ninguno de los extremos antes de que el procesador se comunique con el procesador.

Sintaxis para enviar sincrónica:

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

4. Modo Listo

A diferencia de los tres modo anterior, un envío en el modo de lista se puede iniciar sólo si el receptor que corresponda ya ha sido publicado. La finalización del envío no indica nada acerca de la recepción coincidente y simplemente dice que el búfer de envío se puede reutilizar. Un envío que utiliza el modo listo tiene la misma semántica que el modo estándar o un modo síncrono con la información adicional sobre una recepción coincidente. Un programa correcto con un modo de comunicación preparado puede reemplazarse con envío síncrono o un envío estándar sin efecto en el resultado, aparte de la diferencia de rendimiento.

Sintaxis para enviar listo:

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

Afortunadamente MPI decidió mantener las cosas easer para los usuarios en cuanto a recibir y sólo hay una recepción en el bloqueo de la comunicación: MPI_Recv, y se puede utilizar con cualquier de los cuatro modos de envío descritos anteriormente. Para MPI_Recv, bloqueando significa que recibe devoluciones solo después de que contiene los datos en su búfer. Esto implica que la recepción puede completarse solo después de que se haya iniciado un envío coincidente, pero no implica si puede completarse o no antes de que se complete el envío coincidente.

Lo que sucede durante tales llamadas de bloqueo es que los cálculos se detienen hasta que se libera el búfer bloqueado. Esto generalmente conduce al desperdicio de recursos computacionales ya que Send/Recv usualmente copia datos desde una ubicación de memoria a otra ubicación de memoria, mientras que los registros en la CPU permanecen inactivos.

NO bloqueando la comunicación: Para no bloquear la comunicación, la aplicación crea una solicitud de comunicación para enviar y/o recibir y vuelve un mango y luego termina. Eso es todo lo que se necesita para garantizar que el proceso se ejecute. Es decir, se notifica a la biblioteca MPI que la operación debe ser ejecutada.

Para el lado del emisor, esto permite la superposición del cálculo con la comunicación.

Para el lado del receptor, esto permite superponer una parte de la sobrecarga de comunicación, es decir, copiar el mensaje directamente en el espacio de direcciones del lado receptor en la aplicación.