#include <netpbm/pgm.h>
#include <stdio.h>
#include <mpi.h>
#include <sys/time.h>
FILE *in,*out;
gray **imageIN, **imageOUT;
int width,height,maxg;
int root = 0;
char name[80];
int rank,size,length,rozmiar;
int i,j,k;
double start,end;
int min,max;
int sliceWidth,*recvbuf,*displacement,*slice;
int main(int argc, char *argv[]){
// stworzenie uchwytów do plików
in = fopen("/mhome/mjedrzejas/projekt_koncowy/balloons.pgm","r");
out = fopen("/mhome/mjedrzejas/projekt_koncowy/mandrill_modified.pgm","w");
if (in == NULL)
{
printf("Nie odnaleziono obrazow do otwarcia.\n");
exit(1);
}
// zaladowanie zdjecia
imageIN = pgm_readpgm(in,&width,&height,&maxg);
imageOUT = pgm_allocarray(width,height);
rozmiar = width*height;
// deklarowanie tablic
int sendbuf[rozmiar]; /* cały obraz jako wektor */
//int displacement[PROCESOROW]; /* przesunięcie, określa gdzie zaczyna sie każdy z fragmentów */
//int slice[PROCESOROW]; /* ilość fragmentów*/
// Inicjalizacja środowiska MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size); /* ilość procesorów */
MPI_Get_processor_name(name,&length);
sliceWidth = width/size + 1; /* wielkość na jeden procesor */
recvbuf = (int*)malloc(sliceWidth*height*sizeof(int)); /* wektor fragmentu*/
displacement = (int*)malloc(size*sizeof(int)); /* przesunięcie, określa gdzie zaczyna sie każdy z fragmentów */
slice = (int*)malloc(size*sizeof(int)); /* ilość fragmentów*/
if(rank == root)
{
printf("procesorow %d\n",size);
// pomiar czasu
// przepisanie danych zdjęcia z tablicy gray na tablice int,
// zmienna gray jest zmienna bez znaku i poza tym nie obsługuje jej MPI
for(j=0; j<height; j++)
for(i=0,k=j*height; i<width; i++,k++)
sendbuf[k] = imageIN[j][i];
// obliczanie przesunięcia (początków fragmentów danych) oraz wielkości tych fragmentów
for(i=0; i<size; i++)
{
displacement[i] = i*(rozmiar/size) - i*(height) /* -i*height ze względu na zakładki*/;
slice[i] = height*(width/size) + height; /* + height bo zakładka (aby filtr miał dane) */
}
}
start = MPI_Wtime();
// rozesłanie danych do wszystkich procesorów
MPI_Scatterv(sendbuf,slice,displacement,MPI_INT,recvbuf,sliceWidth*height,MPI_INT,root,MPI_COMM_WORLD);
// deklaracja tablicy z wynikami obliczeń danego fragmentu danych
int recvbuf2[sliceWidth*height];
/*
filtracja obrazu filtrem
0 1 0
1 -4 1
0 1 0
*/
for(i=width; i<(height*width)-width; i++)
recvbuf2[i] = -4*recvbuf[i] + recvbuf[i-1] + recvbuf[i+1] + recvbuf[i-width] + recvbuf[i+width];
if(rank == root)
{
// obliczenie wielkości pojedynczego slice'a
int displacement[size];
int slice[size];
for(i=0; i<size; i++)
{
displacement[i] = i*(rozmiar/size) - i*(height) /* -i*height ze względu na zakładki*/;
slice[i] = rozmiar/size ;
}
}
// odebranie przetworzonych danych
MPI_Gatherv(recvbuf2,(width/size)*height,MPI_INT,sendbuf,slice,displacement,MPI_INT,root,MPI_COMM_WORLD);
end = MPI_Wtime();
if(rank == root)
{
// ustawiamy zmienne po wyszukania minimum i maximum w celu normalizacji
min = sendbuf[0];
max = sendbuf[0];
// wyszukiwanie minimum i maximum
for(i=0; i<rozmiar; i++)
{
if(sendbuf[i] < min)
min = sendbuf[i];
if(sendbuf[i] > max)
max = sendbuf[i];
}
// normalizacja do przedziały [0,255]
for(i=0; i<rozmiar; i++)
sendbuf[i] = ((double)(sendbuf[i] - min))*255/(max-min);
// przepisanie przetworzonego obrazu ponownie do tablicy typu gray
for(j=0;j<height;j++)
for(i=0,k=j*width;i<width;i++,k++)
imageOUT[j][i] = sendbuf[k];
// zapisanie przetworzonego zdjęcia
pgm_writepgm(out,imageOUT,width,height,maxg,0);
// oblieczenie czasu obliczeń oraz wypisanie wyniku
printf("Czas obliczen wynosi: %f \n", end-start);
}
// zwalnianie zasobów
if(rank == root)
{
free(imageIN);
free(imageOUT);
fcloseall();
}
MPI_Finalize();
}