utorok, 27 december 2011 14:42 Written by 8673 times
Rate this item
(1 Vote)

C++ - Paralelné násobenie matíc

Zadanie: Vypracujte program v prostredí MPI v jazyku C, ktorý parelelne vynásobí matice. Zadenie riešte pomocou modelu SPMD a to odovzdávaním správ a skupinovou komunikáciou. Problém vhodne dekomponujte.

Program pracuje podobne ako transponovanie matice. Máme dané dve matice o veľkosti 4x4 a jednu maticu (vektor) o veľkosti 1x4. Prvá matica A je rozdelená na 4 riadky o veľkosti 1x4. Druhá matica B je veľkosti 4x4. Násobíme maticu A maticou B, čím vznikne matica C, tiež o veľkosti 4x4. Nenásobíme naraz všetky riadky, ale každý riadok si rozdelíme na 4 kroky. Teda násobením prvého riadku matice A (1x4) násobíme 4 stĺpce matice B, čím vznikne prvý riadok matice C (1x4). A takto pokračujeme s ostatnými riadkami. Opäť kvôli predbiehaniu procesov je potrebné vypočítané matice od jednotlivých procesov označiť číselne riadkami. Riešenie problému nie je škálovateľné, teda vyžaduje na svoje správne vyriešenie presne 5 procesov. Program obsahuje aj medzikroky, kde sa počíta doba za akú dané procesy vypočítali čiastkové úseky kódu.

Kód v cpp

#include <stdio.h>
#include <mpi.h>

void Matrix_Mult(int a1[][4], int a2[][4], int a3[][4])
{
   int i = 0;
   int j = 0;
   int k = 0;
   
       for(i = 0; i < 1; i++) 
       {
           for( j = 0; j < 4; j++)
           {
               for( k = 0; k < 4; k++) 
               {
                   a3[i][j] +=  a1[i][k] * a2[k][j];
               }
           }
       }
}
void PrintMatrix(int ar[][4])
{
    int i = 0;
    int j = 0;
    for(i = 0; i < 1; i++)
    {
        for( j = 0; j < 4; j++)
        {   
            printf("%4d", ar[i][j]);
        }
            
        putchar('\n'); 
    }
}
void PrintMatrix_N(int ar[][4])
{
    int i = 0;
    int j = 0;
    for(i = 0; i < 4; i++)
    {
        for( j = 0; j < 4; j++)
        {   
            printf("%4d", ar[i][j]);
        }
        putchar('\n'); 
    }
}

int main(int argc, char *argv[])
{
  
  int size, rank;
  double t1, t2;
  
  int A1[1][4] = {
                    {5, 7, 8, 9}
                    },
      A2[1][4] = {
                    {1, 2, 3, 4}
                    },
      A3[1][4] = {
                    {9, 8, 8, 7}
                    },                            
      A4[1][4] = {
                    {1, 1, 2, 1}
                    },            
       B[4][4] = {
                  {1, 1, 1, 2},
                  {2, 3, 4, 5},
                  {7, 7, 8, 1},
                  {0, 4, 5, 0}
                  },
                  
       C[1][4] = {
                  {0, 0, 0, 0}
                  },
                  
       C_vzor[4][4] = {
                  {75, 118, 142, 53},
                  {26, 44, 53, 15},
                  {81, 117, 140, 66},
                  {17, 22, 26, 9}
                  };           
  
  MPI_Status status;
  MPI_Request request;
  
  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  
  
  if(size == 5)
  {
          
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);  
     MPI_Bcast(B, 16, MPI_INT, 0, MPI_COMM_WORLD);  
     MPI_Bcast(C, 4, MPI_INT, 0, MPI_COMM_WORLD);               
             
             
     if(rank == 0) 
     { 
             t1 = MPI_Wtime();
             
         printf("\n\nMatica A:\n");
         PrintMatrix(A1);PrintMatrix(A2);PrintMatrix(A3);PrintMatrix(A4);    
             
         printf("\n\nMatica B:\n");    
         PrintMatrix_N(B);
         
         printf("\n\nMatica C - vzorova:\n");    
         PrintMatrix_N(C_vzor);    
         
         printf("\n\n\nVysledok:\n"); 
             
         MPI_Send(A1, 4, MPI_INT, 1, 01, MPI_COMM_WORLD);
         MPI_Send(A2, 4, MPI_INT, 2, 02, MPI_COMM_WORLD);   
         MPI_Send(A3, 4, MPI_INT, 3, 03, MPI_COMM_WORLD);
         MPI_Send(A4, 4, MPI_INT, 4, 04, MPI_COMM_WORLD);
         
         t2 = MPI_Wtime();
        
          printf("\nvypocet casu (rank 0): %f\n", t2-t1);
          fflush(stdout);
     }
     else if(rank == 1)
     {
          
          t1 = MPI_Wtime();
          
          MPI_Recv(A1, 4, MPI_INT, 0, 01, MPI_COMM_WORLD, &status);
          Matrix_Mult(A1, B, C);
          printf("\n\n1.riadok:\n");
          PrintMatrix(C);
          
          t2 = MPI_Wtime();
        
          printf("\nvypocet casu (rank 1): %f\n", t2-t1);
          fflush(stdout);
     }
     else if(rank == 2)
     {
          t1 = MPI_Wtime();
          
          MPI_Recv(A2, 4, MPI_INT, 0, 02, MPI_COMM_WORLD, &status);
          Matrix_Mult(A2, B, C);
          printf("\n\n2.riadok:\n");
          PrintMatrix(C);
          
          t2 = MPI_Wtime();
        
          printf("\nvypocet casu (rank 2): %f\n", t2-t1);
          fflush(stdout);
     }
     else if(rank == 3)
     {
          t1 = MPI_Wtime();
          
          MPI_Recv(A3, 4, MPI_INT, 0, 03, MPI_COMM_WORLD, &status);
          Matrix_Mult(A3, B, C);
          printf("\n\n3.riadok:\n");
          PrintMatrix(C);
          
          t2 = MPI_Wtime();
        
          printf("\nvypocet casu (rank 3): %f\n", t2-t1);
          fflush(stdout);
     }
     else if(rank == 4)
     {
          t1 = MPI_Wtime();
          
          MPI_Recv(A4, 4, MPI_INT, 0, 04, MPI_COMM_WORLD, &status);
          Matrix_Mult(A4, B, C);
          printf("\n\n4.riadok:\n");
          PrintMatrix(C);
          
          t2 = MPI_Wtime();
        
          printf("\nvypocet casu (rank 4): %f\n", t2-t1);
          fflush(stdout);
     }
    
}
    
  
  
  MPI_Finalize();
  return(0);
}

 

Last modified on pondelok, 26 október 2015 12:31