Προς το περιεχόμενο

Αποστολή και λήψη πίνακα nxn σε MPI


pagratios

Προτεινόμενες αναρτήσεις

Δημοσ.

Προσπαθώ να στείλω έναν πίνακα από μία διεργασία σε άλλη και λαμβάνει μόνο την πρώτη γραμμή τι πρέπει να κάνω ακριβώς?

 

>int main(int argc, char** argv)
{

   double **a, **b; **c, start, end;
   int i, j, n,N, M, myrank, numprocs,k,kk,x,y,p,u;
   MPI_Status recv_status;
   MPI_Request recv_req, send_req;
   MPI_Datatype new_type;

   M=atoi(argv[1]);

   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
   MPI_Comm_rank(MPI_COMM_WORLD,&myrank);



   if(fmod(M,sqrt(numprocs)) != 0)
   {


       if(myrank == 0)
           puts("edose kathos N!");
       MPI_Finalize();
       exit(-1);
   }

   
   n=M/sqrt(numprocs);     //to megethos ton ipopinakon tis kathe diergasias
   N=sqrt(numprocs);

   a =malloc(n*sizeof(double*));
   b =malloc(n*sizeof(double*));
   c =malloc(n*sizeof(double*));


   for(i=0;i<n;i++)
   {
       a[i]=malloc(n*sizeof(double));
       b[i]=malloc(n*sizeof(double));
       c[i]=malloc(n*sizeof(double));

   }
   



   for(i=0;i<n;i++)
       for(j=0;j<n;j++)
       {
           c[i][j] = 0;
           a[i][j] = myrank;
           b[i][j] = myrank;
       }
       


   if(myrank == 0)
       start = MPI_Wtime();

for(i=0;i<n;i++)
if(myrank / N != 0)
{
	MPI_Send(*a, n*n, MPI_DOUBLE, desta(myrank / N,myrank,N),15,MPI_COMM_WORLD);
	MPI_Recv(*a, n*n, MPI_DOUBLE, sourcea(myrank / N,myrank,N),15,MPI_COMM_WORLD, &recv_status);
}

for(i=0;i<n;i++)
if(myrank % N != 0)
{
	MPI_Send(*b, n*n, MPI_DOUBLE, destb(myrank % N,myrank,N),15,MPI_COMM_WORLD);
	MPI_Recv(*b, n*n, MPI_DOUBLE, sourceb(myrank % N,myrank,N),15,MPI_COMM_WORLD, &recv_status);
}


//pollaplasiasmos tou c
for(i=0;i<n;i++)
	for(k=0;k<n;k++)
		for(j=0;j<n;j++)
			c[i][k] += a[i][j]*b[j][k];









if(myrank == 3)
       {
           printf("Eimai i %d gia ton a pinaka\n",myrank);
           for(i=0;i<n;i++)
           {
               for(j=0;j<n;j++)
                   printf("%lf ",a[i][j]);
               puts("");
           }
           printf("Eimai i %d gia ton b pinaka\n",myrank);
           for(i=0;i<n;i++)
           {
               for(j=0;j<n;j++)
                   printf("%lf ",b[i][j]);
               puts("");
           }
           printf("Eimai i %d gia ton c pinaka\n",myrank);
           for(i=0;i<n;i++)
           {
               for(j=0;j<n;j++)
                   printf("%lf ",c[i][j]);
               puts("");
           }
      }




  
   for(i=0;i<n;i++)
   {
       free(a[i]);
       free(b[i]);
       free(c[i]);
   }

   free(a);
   free(;
   free(c);
   

   MPI_Finalize();


   return 0;
}

Δημοσ.

Μικρο-διόρθωση αλλά αφού το είδα...

>puts("edose [b]k[/b]athos N!");

Γιατί το κάνεις sqrt?

>n=M/sqrt(numprocs);
N=sqrt(numprocs);

Επίσης δεν θα ήταν προτιμότερο να τις βάλεις αντίστροφα αυτές τις δυο σειρές?

>
N=sqrt(numprocs);
n=M/N;

 

Αντί για

>MPI_Send(*a, n*n, MPI_DOUBLE, desta(myrank / N,myrank,N),15,MPI_COMM_WORLD);

μήπως θέλει

>MPI_Send(*[b]*[/b]a, n*n, MPI_DOUBLE, desta(myrank / N,myrank,N),15,MPI_COMM_WORLD);

 

Συνεχίζοντας, μήπως θα βόλευε να μετατρέψεις τους δισδιάστατους πίνακες σε μονοδιάστατους?

>
a =malloc(n*n*sizeof(double*));
b =malloc(n*n*sizeof(double*));
c =malloc(n*n*sizeof(double*));

int counter = 0;
for(i=0;i<n;i++)
       for(j=0;j<n;j++)
       {
           counter = i*n+j;
           c[counter] = 0;
           a[counter] = myrank;
           b[counter] = myrank;
       }

 

Το ακόλουθο είναι απαραίτητο?

>    for(i=0;i<n;i++)
   {
       free(a[i]);
       free(b[i]);
       free(c[i]);
   }

   free(a);
   free(;
   free(c);

Δεν μπορείς να κάνεις απευθείας "free(x)"?

Δημοσ.

Δεν μας δίνεις τα sourcea, sourceb, desta, destb για να μπορούμε να το τρέξουμε και να πειραματιστούμε στην πράξη...

 

Eξάλλου, αναρωτιέμαι ποιά μπορεί να είναι η χρησιμότητα του MPI σε κοινούς προγραμματιστές (επαγγελματίες ή ερασιτέχνες).

Οι υπολογιστές που είναι πραγματικά κατανεμημένης μνήμης (clusters) δεν είναι αντικείμενο της καθημερινότητας, δεν έχω δει σχεδόν κανέναν ιδιώτη να έχει cluster.

Όλοι οι επιτραπέζοι υπολογιστές είναι διαμοιραζόμενης μνήμης και συνεπώς το υλοποιούν με νήματα, έτσι υποθέτω τουλάχιστον.

Π.χ. στο visual studio όταν καθορίζω πόσες θα είναι οι διεργασίες που τρέξουν, με νήματα δεν τις τρέχει ; (αφού μπορεί να τρέχει και σε μονοπύρηνο για αυθαίρετο πλήθος διεργασιών...)

Όποιος ξέρει σχετικά ας μας πει τι γίνεται...

Δημοσ.

Είναι εργασία για την σχολή μου.

 

Οι free μπορεί να γίνονται και όπως λες, αλλά και πάλι δεν πετάει πρόβλημα.

 

Το πρόγραμμα δεν είναι μόνο αυτό και δεν έχει κάποιο ουσιαστικό πρόβλημα απλά ήθελα να δω αν γίνεται να στείλω όλο τον πίνακα της καθε διεργασίας και όχι γραμμή γραμμή.

 

Τελικά το στέλνω γραμμή γραμμή κάνοντας το εξής

for(i=0;i<n;i++)

MPI_Send(a, n, MPI_DOUBLE, desta(myrank / N,myrank,N),15,MPI_COMM_WORLD);

 

Γιατί να κάνω ανάποδα το εξής?

N=sqrt(numprocs);

n=M/N;

 

Έχεις δίκιο θα το αλλάξω

 

Δεν γίνεται το

MPI_Send(**a, n*n, MPI_DOUBLE, desta(myrank / N,myrank,N),15,MPI_COMM_WORLD);

 

επειδή η συνάρτηση δέχεται void * στο αντικείμενο που θα στείλουμε

  • 2 εβδομάδες αργότερα...
Δημοσ.

Τα array σου δεν είναι σε contiguous memory - οπότε πρέπει να πεις στο ακριβώς που βρίσκεται τι.

 

Δες το παρακάτω (C++, όχι C):

 

>
#include <mpi.h>
#include <iostream>

int main(void)
{
 MPI_Init(0,0);

 int rank = MPI_PROC_NULL;
 int size = MPI_PROC_NULL;

 MPI_Comm_size(MPI_COMM_WORLD, &size);
 MPI_Comm_rank(MPI_COMM_WORLD, &rank);

 // create dynamically allocated double NxM matrix
 const std::size_t N = 2, M = 4;
 double **d = new double*[N];
 for (std::size_t i=0; i<N; ++i) {
   d[i] = new double[M];
 }

 // register new type
 MPI_Datatype matrix_type;
 int *block_length  = new int[N];
 MPI_Aint *displ    = new MPI_Aint[N];
 MPI_Datatype *type = new MPI_Datatype[N];
 for (std::size_t i=0; i<N; ++i) {
   block_length[i] = M;
   displ[i]        = (char*)&d[i][0] - (char*)&d[0];
   type[i]         = MPI_DOUBLE;
 }
 MPI_Type_create_struct(N, block_length, displ, type, &matrix_type);
 delete block_length;
 delete displ;
 delete type;
 MPI_Type_commit(&matrix_type);

 if (rank==0) {
   // initialize matrix
   for (std::size_t i=0; i<N; ++i) {
     for (std::size_t j=0; j<M; ++j) {
       d[i][j] = i + 2*j;
     }
   }

   std::cout << "Sending: " << std::endl;
   for (std::size_t i=0; i<N; ++i) {
     for (std::size_t j=0; j<M; ++j) {
       std::cout << d[i][j] << ' ';
     }
     std::cout << std::endl;
   }
   std::cout << std::endl;

   MPI_Send(d, 1, matrix_type, 1, 0, MPI_COMM_WORLD);
 }
 else if (rank==1) {
   MPI_Recv(d, 1, matrix_type, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

   std::cout << "Received: " << std::endl;
   for (std::size_t i=0; i<N; ++i) {
     for (std::size_t j=0; j<M; ++j) {
       std::cout << d[i][j] << ' ';
     }
     std::cout << std::endl;
   }
   std::cout << std::endl;
 }

 // release memory
 for (std::size_t i=0; i<N; ++i) {
   delete[] d[i];
 }
 delete d;

 MPI_Type_free(&matrix_type);
 MPI_Finalize();

 return 0;
}

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...