Untitled

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

char* help = "\n\
   ** Matrix_Mult_MPI.c ** \n\
   Algoritm MPI de inmultire a doua matrice \n\
   \n\
   Se compileaza: \n\
   mpicc Matrix_Mult_MPI.c -o Matrix_Mult_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 Matrix_Mult_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;           // Dim matrice
        int p = 1;   		// Nr procese MPI 
        int max_rep = 1;	// Numar de repetari executie

        int root = 0; 
	int rank; 		// rangul procesului (q)
      	int i, j, k, s, rep;

	struct timeval t1, t2;
	float tp;
	FILE * fp;
        char* fn = "Res_Matrix_Mult_MPI.txt";
        
        // 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]);

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

        // 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;

        // Alocarea matricelor
	float **a = (float**)malloc(sizeof(float*)*n);
   	
   	float *c = (float*)malloc(sizeof(float*)*n);
   	float *ma = (float*)malloc(sizeof(float)*n*n);    
   
   	for (i = 0; i < n; i++){
       	   a[i] = ma; ma += n;
          
        }

    	// Initializare matrice a, b
        if (rank == root){

    	  
             for (i = 0; i < n; i++)
                for (j = 0; j < n; j++) {
                    a[i][j] = 1;
                        
                } 
               
              gettimeofday(&t1, NULL);
       }

       for (rep = 0; rep < max_rep; rep++){
	  //
          // Inmultire secventiala daca p = 1
          //
	  if (p == 1){
	     for (i = 0; i < n; i++)  {
              c[i] = 0;
	         for (j = 0; j < n; j++){ 
		    
		        c[i] += a[i][j] ;  
    	         } 
             }
	  }
	  //
	  // Inmultire paralela (p > 1)
          else {
              // Transmitere matrice a, b 
	      if (rank == root && root == 0)
	      	   MPI_Scatter(a[0], s*n, MPI_FLOAT, MPI_IN_PLACE, s*n, MPI_FLOAT, root, MPI_COMM_WORLD);
	      else MPI_Scatter(a[0], s*n, MPI_FLOAT, a[0], s*n, MPI_FLOAT, root, MPI_COMM_WORLD);        
	      

	      // Inmultire submatrice de s linii in fiecare proces
	     for (i = 0; i < s; i++)  {
              c[i] = 0;
	         for (j = 0; j < n; j++){ 
		    
		        c[i] += a[i][j] ;  
    	         } 
 

	      // Colectare rezultate
	      if (rank == root && root == 0)
	     	  MPI_Gather(MPI_IN_PLACE, s, MPI_FLOAT, c, s, MPI_FLOAT, root, MPI_COMM_WORLD);
	      else MPI_Gather(c, s, MPI_FLOAT, c, s, MPI_FLOAT, root, MPI_COMM_WORLD);

          }  // end else
       }   // end rep

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

           printf("%d rep, n = %d, p = %d, t = %f sec\n", max_rep, n, p, tp);

	   if (n <= 16) 
           {
		for (i = 0; i < n; i++) {
		    
			 printf("%4.0f   ", c[i]);
	    	    
		}
           }
       }

      MPI_Finalize();
      return 0;
}
}