1. Indice de pagina
  2. 1. Objetivos
  3. 2. Enunciado
  4. 2.1. Pistas
  5. 2.2. Funciones necesarias
  6. 3. Solución
  7. 3.1. Código
  8. 3.2. Salida

Comunicadores

Objetivos

Enunciado

Crea 3 comunicadores nuevos (MPI_Comm_split):

Una vez obtenidos los comunicadores, el proceso 0 (del comunicador global) tendrá inicialmente variables (que denominaremos 'a' y 'b') que valdrán 2000 y 1 respectivamente. El resto de procesos tendrán esas dos variables inicializadas con el valor 0. El proceso 0 (en el comunicador global) difundirá el valor 'a' por el comunicador asociado a los procesos pares, con lo que el grupo de impares no debería recibir el nuevo valor de 'a'. Respecto al valor de 'b', el proceso 0 (en el comunicador global) deberá difundirlo por el tercer comunicador (el de rangos inversos) y todos los procesos deberían recibirlo.
Comprueba que los valores recibidos son correctos.

Imagen Tutorial 7 Comunicadores (Pulsar sobre la imagen para ver la animación)

Pistas

Ten en cuenta que el proceso que conoce los valores debe ser el proceso 0 dentro del comunicador global, pero dentro de comunicador invertido no tendrá el rango 0.

Funciones necesarias

Solución

Código Descarga

#include "mpi.h"
#include <vector>
#include <cstdlib>
#include <iostream>
using namespace std;
 
int main(int argc, char *argv[]) {
    int rank, size;
 
    MPI_Init(&argc, &argv); //iniciamos el entorno MPI
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); //obtenemos el identificador del proceso
    MPI_Comm_size(MPI_COMM_WORLD, &size); //obtenemos el numero de procesos
 
    MPI_Comm comm // nuevo comunicador para pares o impares
            , comm_inverso; // nuevo para todos los procesos pero con rank inverso.
    int rank_inverso, size_inverso;
    int rank_nuevo, size_nuevo;
    int a;
    int b;
 
    if (rank == 0) {
        a = 2000;
        b = 1;
    } else {
        a = 0;
        b = 0;
    }
 
    int color = rank % 2;
    // creamos un nuevo cominicador
    MPI_Comm_split(MPI_COMM_WORLD // a partir del comunicador global.
            , color // los del mismo color entraran en el mismo comunicador
            // lo pares tiene color 0 y los impares 1.
            , rank, // indica el orden de asignacion de rango dentro de los nuevos
comunicadores
            &comm); // Referencia al nuevo comunicador creado.
    // creamos un nuevo comunicador inverso.
    MPI_Comm_split(MPI_COMM_WORLD, // a partir del comunicador global.
            0 // el color es el mismo para todos.
            , -rank // el orden de asignacion para el nuevo rango es el inverso al actual.
            , &comm_inverso); // Referencia al nuevo comunicador creado.
 
    MPI_Comm_rank(comm, &rank_nuevo); // obtenemos el nuevo rango asignado dentro de comm
    MPI_Comm_size(comm, &size_nuevo); // obtenemos numero de procesos dentro del
comunicador
 
    MPI_Comm_rank(comm_inverso, &rank_inverso); // obtenemos el nuevo rango asignado en
comm_inverso
    MPI_Comm_size(comm_inverso, &size_inverso); // obtenemos numero de procesos dentro del
comunicador
 
    //Probamos a enviar datos por distintos comunicadores
    MPI_Bcast(&b, 1, MPI_INT,
            size - 1, // el proceso con rango 0 dentro de MPI_COMM_WORLD sera root
            comm_inverso);
    MPI_Bcast(&a, 1, MPI_INT,
            0, // el proceso con rango 0 dentro de comm sera root
            comm);
 
    cout << "Soy el proceso " << rank << " de " << size << " dentro de MPI_COMM_WORLD,"
            "\n\t mi rango en COMM_nuevo es " << rank_nuevo << ", de " << size_nuevo <<
			", aqui he recibido el valor " << a <<
            ",\n\ten COMM_inverso mi rango es " << rank_inverso << " de " << size_inverso
<<
			" aqui he recibido el valor " << b <<"\n"<< endl;
 
 
    MPI_Finalize();
    return 0;
}

Salida

> mpiCC comunicadores.cpp -o c
> mpirun -np 10 c
Soy el proceso 0 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 0, de 5, aqui he recibido el valor 2000,
en COMM_inverso mi rango es 9 de 10 aqui he recibido el valor 1

Soy el proceso 1 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 0, de 5, aqui he recibido el valor 0,
en COMM_inverso mi rango es 8 de 10 aqui he recibido el valor 1

Soy el proceso 5 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 2, de 5, aqui he recibido el valor 0,
en COMM_inverso mi rango es 4 de 10 aqui he recibido el valor 1

Soy el proceso 8 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 4, de 5, aqui he recibido el valor 2000,
en COMM_inverso mi rango es 1 de 10 aqui he recibido el valor 1

Soy el proceso 6 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 3, de 5, aqui he recibido el valor 2000,
en COMM_inverso mi rango es 3 de 10 aqui he recibido el valor 1

Soy el proceso 4 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 2, de 5, aqui he recibido el valor 2000,
en COMM_inverso mi rango es 5 de 10 aqui he recibido el valor 1

Soy el proceso 3 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 1, de 5, aqui he recibido el valor 0,
en COMM_inverso mi rango es 6 de 10 aqui he recibido el valor 1

Soy el proceso 7 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 3, de 5, aqui he recibido el valor 0,
en COMM_inverso mi rango es 2 de 10 aqui he recibido el valor 1

Soy el proceso 2 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 1, de 5, aqui he recibido el valor 2000,
en COMM_inverso mi rango es 7 de 10 aqui he recibido el valor 1

Soy el proceso 9 de 10 dentro de MPI_COMM_WORLD,
mi rango en COMM_nuevo es 4, de 5, aqui he recibido el valor 0,
en COMM_inverso mi rango es 0 de 10 aqui he recibido el valor 1
Creado por: Daniel Guerrero Martínez y Sergio Rodríguez Lumley 2010

Valid HTML 4.01 Transitional