Pro
gramowanie równoległe i współbieżne
Ćwiczenie:
Ćwiczenie 4
Data oddania:
15.4.2013
Imię, Nazwisko:
Kulecka Aleksandra
Ocena:
Uwagi:
1.
Cel ćwiczenia
Celem ćwiczenia było zapoznanie się z komunikacją punktową w MPI na podstawie dwóch
sposób przesyłania komunikatu (ping-pong oraz token).
2.
Kod źródłowy wraz z objaśnieniem
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include "mpi.h"
using namespace std;
int main( int argc, char *argv[] )
{
int rank, dest;
int size;
int inmsg, tag = 1;
int rc, source;
MPI_Status Stat;
MPI_Init( 0, 0 );
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int count = 2;
if(rank == 0)
{ dest = rank + 1;
source = size - 1;
inmsg = 0;
for (int i = 0; i < count; i++ )
{
rc = MPI_Send(&inmsg,1,MPI_INT,dest,tag,MPI_COMM_WORLD);
cout << "Proces " << rank << " wyslano do " << dest <<" liczbe " <<inmsg <<endl;
inmsg += 1;
rc = MPI_Recv(&inmsg,1,MPI_INT,source,tag,MPI_COMM_WORLD,&Stat);
cout << "Proces " << rank << " odebrano od " << source <<" liczbe " <<inmsg<<endl;
}
}else if(rank == (size-1))
{
source = rank - 1;
dest = 0;
for (int i = 0; i < count; i++ )
{
rc = MPI_Recv(&inmsg,1,MPI_INT,source,tag,MPI_COMM_WORLD,&Stat);
cout << "Proces " << rank << " odebrano od " << source <<" liczbe " <<inmsg<<endl;
inmsg += 1;
rc = MPI_Send(&inmsg,1,MPI_INT,dest,tag,MPI_COMM_WORLD);
cout << "Proces " << rank << " wyslano do " << dest <<" liczbe " <<inmsg <<endl;
}
}else
{
source = rank - 1;
dest = rank + 1;
for (int i = 0; i < count; i++ )
{
rc = MPI_Recv(&inmsg,1,MPI_INT,source,tag,MPI_COMM_WORLD,&Stat);
cout << "Proces " << rank << " odebrano od " << source <<" liczbe " <<inmsg<<endl;
inmsg += 1;
rc = MPI_Send(&inmsg,1,MPI_INT,dest,tag,MPI_COMM_WORLD);
cout << "Proces " << rank << " wyslano do " << dest <<" liczbe " <<inmsg <<endl;
}
}
MPI_Finalize();
return 0;
}
Kolorem
żółtym oznaczono fragment, w którym załączam 4 podstawowe biblioteki, służące do
wykorzystywania charakterystycznych poleceń w programie (np. polecenie cout, cin, MPI_Send,...).
Kolorem jasnozielonym oznaczono
linijkę, dzięki której, wykorzystanie poleceń z biblioteki iostream,
nie musi zostać poprzedzone każdorazowo odnośnikiem do klasy std (std::cout, std::cin).
Błękitnym kolorem oznaczono deklarację/definicję zmiennych lokalnych, przechowujących rozmiar,
treść, źródło, tag, cel oraz inne parametry komunikatu wysyłanego za pomocą MPI między procesami.
Różowy kolor oznacza zadeklarowanie zmiennych charakterystycznych dla MPI takich jak status
komunikatu, początek pętli przesyłania, wielkość oraz rozmiar komunikatu.
Niebieski kolor oznacza deklarację i definicje zmiennej lokalnej oznaczającej ile razy komunikat będzie
przesłany.
W zależności od numeru procesu, który aktualnie jest rozpatrywany przez program (kolor czerwony)
wykonywane jest pewne polecenie.
Jeśli jest to proces początkowy (rank ==0), to zwiększony staje się numer procesu (komunikat będzie
wysyłany do kolejnego procesu), źródło z którego komunikat w procesie początkowym został
odebrany, jest równy wielkości procesu - 1 (numeracja rozpoczyna się od 0! ). Następnie za
przesyłaną wiadomość podstawia się wartość początkową równą 0. W pętli for, od 0 do licznika
(zadeklarowanego w niebieskim oznaczeniu)
, wykonują się następujące czynności:
Za
zmienną rc podstawiony zostaje wynik funkcji MPI_Send (wiadomość wysłana), które
przyjmuje za zmienne
treść komunikatu do wysłania, zmienną typu MPI_INT, kierunek, do
którego wysyła się komunikat, tag komunikatu, oraz wielkość samego procesu.
N
astępnie zostaje wypisana na ekran informacja o wysłaniu komunikatu oraz jego treści,
źródle i odbiorcy.
W
iadomość zostaje zwiększona o 1.
Ponownie
za zmienną rc podstawiany jest rezultat działa funkcji MPI_Recv (wiadomość
odebrana
), który przyjmuje następujące argumenty: odebrany komunikat,treść, zmienną typu
MPI_INT, źródło komunikatu, tag, wielkość procesu oraz aktualny status.
Wyświetlona zostaje informacja o odebraniu komunikatu ze źródłem, treścią komunikatu oraz
odborcy.
Jeśli proces nie jest procesem początkowym, a końcowym, wówczas, za źródło przyjmuje się wielkość
procesu -
1 (numeracja następuje od 0!), odbiorcą (czy przeznaczeniem komunikatu) jest proces
początkowy - 0, a następnie zostaje wykonana pętla for o dokładnie takim samym działaniu jak w
pierwszym przyadku (odebranie wiadomości, zapisanie stanu do zmiennej, wyświetlenie informacji o
postępie, zwiększenie komunikatu, wysłanie komunikatu, wypisanie informacji o wysłaniu).
Jeśli natomiast proces znajduje się pomiędzy początkiem a końcem (i nie jest ani początkiem, ani
końcem), wówczas za źródło podstawiana wielkość procesu - 1, za przeznaczenie wielkość
procesu + 1, a do
piero później wykonywana jest pętla for.
Polecenie
MPI_Finalize(); zamyka pętlę przesyłania komunikatu.
Polecenie
return 0; zwraca wartość 0 z funkcji głównej main.