24 noiembrie 2010

Sortare OETS in MPI

Pentru descrierea problemei vezi si OETS in OpenMP .

=======

compilare: mpicc oets.c -o oets
rulare: mpiexec -np 7 oets
(np inseamna nr de procese, identic cu nr de procese angajate sa ruleze in program)

=======

#include "mpi.h"
#include "stdio.h"

int main(argc,argv)
int argc;
char *argv[]; {

int numtasks, rank, dest, source, rc, count, tag=1;
MPI_Status Stat;
int v[7];
v[0] = 5;
v[1] = 3;
v[2] = 6;
v[3] = 8;
v[4] = 4;
v[5] = 2;
v[6] = 7;
int n = 7;

MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

int i;
int val ;
MPI_Scatter (v, 1, MPI_INT, &val, 1, MPI_INT, 0, MPI_COMM_WORLD);

for(i=1;i<=n; i++) {

if(i%2==1) {
if (rank %2 == 0 && rank+1<=n-1) {
dest = rank+1;
source = rank+1;
int val2;
rc = MPI_Send(&val, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
rc = MPI_Recv(&val2, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &Stat);
val = (val < val2)?val:val2;
}
else if(rank%2==1 && rank > 0){
dest = rank-1;
source = rank-1;
int val2;
rc = MPI_Recv(&val2, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &Stat);
rc = MPI_Send(&val, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
val = (val > val2)?val:val2;
}
}
else {
if(rank%2 == 1 && rank+1<=n-1 ) {
dest = rank+1;
source = rank+1;
int val2;
rc = MPI_Send(&val, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
rc = MPI_Recv(&val2, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &Stat);
val = (val < val2)?val:val2;
}
else if(rank%2==0 && rank>0 ) {
dest = rank-1;
source = rank-1;
int val2;
rc = MPI_Recv(&val2, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &Stat);
rc = MPI_Send(&val, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
val = (val > val2)?val:val2;
}
}

MPI_Barrier (MPI_COMM_WORLD);

}

MPI_Gather (&val, 1, MPI_INT, v, 1, MPI_INT, 0, MPI_COMM_WORLD);

if(rank==0) {
for(i=0; i<=6; i++)
printf("%d ", v[i]);
printf("\n");
}

MPI_Finalize();

}

=== explicatii ===

In principiu, pasii sunt la fel ca la varianta in OpenMI, cu deosebirea ca intr-un pas se realizeaza o comunicatie intre oricare 2 procese alaturate, stanga si dreapta. Stanga prin conventie va trimite o valoare in dreapta si va primi valoarea din dreapta dupa care va stoca minimul, iar dreapta primeste o valoare din stanga si si-o trimite si pe a ei in stanga dupa care stocheaza maximul; etc...
MPI_Scatter (v, 1, MPI_INT, &val, 1, MPI_INT, 0, MPI_COMM_WORLD) are semnificatia: din vectorul v se ia cate 1 element, de tip MPI_INT, care se transmite celorlalte procese in variabila val, care este 1 singura valoare, si ea de tip MPI_INT. Root-ul este procesul cu rangul 0, iar mediul este MPI_COMM_WORLD.
MPI_Gather are acelasi tip de parametri, insa cu semnificatia ca valoarea val din fiecare proces este depusa in v.
MPI_Barrier
este pus pentru a se asigura ca la sfarsitul iteratiei fiecare proces si-a terminat treaba.

Niciun comentariu: