Programowanie równoległe i współbieżne
Ćwiczenie:
Ćwiczenie 4
Data oddania:
15.4.2013
Imię, Nazwisko:
Dawid Misiniec
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;
}
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.
Następnie zostaje wypisana na ekran informacja o wysłaniu komunikatu oraz jego treści,
źródle i odbiorcy.
Wiadomość 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 dopiero później wykonywana jest pętla for.
Polecenie
MPI_Finalize(); zamyka pętlę przesyłania komunikatu.