Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
3.8 kB
22
Indexable
Never
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <math.h>
#include <mpi.h>
#include <string.h>

char* help = "\n\
   ** Vector_Add_MPI.c ** \n\
   Algoritm MPI de adunare a doua matrice \n\
   \n\
   Se compileaza: \n\
   mpicc Vector_Add_MPI.c -o Vector_Add_MPI \n\
   \n\
   Se lanseaza cu parametrii n, p max_rep (n divizibil cu p) \n\
   Implicit n = 1024, p = 1, max_rep = 1  \n\
   mpirun -np p Matrix_Mult_MPI n max_rep \n\
   \n\
   Executie in mai multe noduri specificate in fisierul hosts:\n\
   mpirun -hostfile hosts -np p Vector_Add_MPI n \n\
   \n\
   Fisierul hosts contine numele nodurilor (hostname) si numarul de procesoare (slots): \n\
   hpc slots=1 \n\
   compute-0-1 slots=1 \n\
   compute-0-2 slots=1 \n\
   compute-0-3 slots=1 \n";

int main(int argc, char* argv[])
{
        int n = 1024;           	// Dimensiune matrice
        int p = 1;   			// Nr procese MPI (p)
	int max_rep = 1;		// numar de repetari

        int root = 0;
        int rank; 			// Rang proces

	int i, s, rep;  
 	double psum, sum;
     
        float *a,*b;

    	struct timeval t1, t2;	
    	float tp;   
    	char *fn = "Res_Reduction_MPI.txt";	    
    	FILE *fp;

        // Citire parametri
        if (argc >=2 && strcmp(argv[1],"-help") == 0) {
            printf("%s\n",help);
            return 0;
        }
	if (argc >= 2) n = atoi(argv[1]);
        if (argc >= 3) max_rep = atoi(argv[2]);

    	// Testarea parametrilor
    	if (n < 2){
           printf("Eroare: n < 2 \n");
           exit(0);
    	}
    	if (max_rep < 1){
           printf("Eroare: max_rep < 1 \n");
           exit(0);
    	}
        // Initializare MPI
	MPI_Init (&argc,&argv);
	MPI_Comm_rank (MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &p);

        // Alocarea vectorilor    
	a = (float*)malloc(n*sizeof(float));
    b = (float*)malloc(n*sizeof(float));

        // Test n divizibil cu p
        if ( n % p != 0) {
            if (rank == root) printf("Eroare: n = %d nu este divizibil cu p = % d\n",n, p);
            MPI_Finalize();
            exit(0);        
        }
	s = n / p;

        // Initializare date
	if (rank == root) {
            for (i = 0; i < n; i++)
               *(a+i) = 1;
               *(b+i) = 1;

            gettimeofday(&t1, NULL);
        } 
        for (rep = 0; rep < max_rep; rep++) {
            sum = 0;					// Initializare sum
            if (p == 1) {
                // Executie secventiala
                for (i = 0; i < n; i++)
                    sum += a[i]*b[i];
            }
            else {
               // Executie paralela

               if (rank == root && root == 0){
	      	   MPI_Scatter(a, s, MPI_FLOAT, MPI_IN_PLACE, s, MPI_FLOAT, root, MPI_COMM_WORLD);
                 MPI_Scatter(b, s, MPI_FLOAT, MPI_IN_PLACE, s, MPI_FLOAT, root, MPI_COMM_WORLD);
               }

	       else{ MPI_Scatter(a, s, MPI_FLOAT, a, s, MPI_FLOAT, root, MPI_COMM_WORLD);
           MPI_Scatter(b, s, MPI_FLOAT, b, s, MPI_FLOAT, root, MPI_COMM_WORLD);
           }

                  psum = 0;
                  // Reducere locala in partitie
		  for (i = 0; i < s; i++) {
                     psum += a[i]*b[i];
                  }
                  // Reducere globala in root
                  MPI_Reduce(&psum, &sum, 1, MPI_DOUBLE, MPI_SUM,root, MPI_COMM_WORLD);
	    }
        } // end rep

    	gettimeofday(&t2, NULL);
        if (rank == root) {
	    tp = ((float)(t2.tv_sec - t1.tv_sec) + 0.000001*(t2.tv_usec - t1.tv_usec))/max_rep;
    	    // Scriere in fisier
    	    fp = fopen(fn, "a");
    	    if (p == 1) fprintf(fp, "\n%f  ",tp);
   		else fprintf(fp, "%f  ",tp);
    	    fclose(fp);

            printf("%d rep, sum = %f n = %d, p = %d, tp = %f sec\n", rep, (float)sum, n, p, tp);
        }
        MPI_Finalize();
	return 0;
}