Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
first step to separate the host matrix size from the data matrix sizes
[simgrid.git] / examples / gras / pmm / pmm.c
1 /* $Id$ */
2 /* pmm - parallel matrix multiplication "double diffusion"                       */
3
4 /* Copyright (c) 2006- Ahmed Harbaoui. All rights reserved.                  */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include "gras.h"
10 #define PROC_MATRIX_SIZE 3
11 #define SLAVE_COUNT (PROC_MATRIX_SIZE*PROC_MATRIX_SIZE)
12
13 #define DATA_MATRIX_SIZE 3
14
15 XBT_LOG_NEW_DEFAULT_CATEGORY(pmm,"Parallel Matrix Multiplication");
16
17 GRAS_DEFINE_TYPE(s_matrix,struct s_matrix {
18   int rows;
19   int cols;
20   double *data GRAS_ANNOTE(size, rows*cols);
21 };)
22 typedef struct s_matrix matrix_t;
23
24 /* struct for recovering results */
25 GRAS_DEFINE_TYPE(s_result,struct s_result {
26   int i;
27   int j;
28   double value;
29 });
30 typedef struct s_result result_t;
31
32 /* struct to send initial data to slave */
33 GRAS_DEFINE_TYPE(s_init_data,struct s_init_data {
34   int myrow;
35   int mycol;
36   double a;
37   double b;
38 });
39 typedef struct s_init_data init_data_t;
40
41 /* register messages which may be sent (common to client and server) */
42 static void register_messages(void) {
43   gras_datadesc_type_t result_type;
44   gras_datadesc_type_t init_data_type;
45   result_type=gras_datadesc_by_symbol(s_result);
46   init_data_type=gras_datadesc_by_symbol(s_init_data);
47         
48   gras_msgtype_declare("result", result_type);  // recieve a final result from slave
49   gras_msgtype_declare("init_data", init_data_type);  // send from master to slave to initialize data bA,bB
50
51   gras_msgtype_declare("ask_result", gras_datadesc_by_name("int")); // send from master to slave to ask a final result  
52   gras_msgtype_declare("step", gras_datadesc_by_name("int"));// send from master to slave to indicate the begining of step 
53   gras_msgtype_declare("step_ack", gras_datadesc_by_name("int"));//send from slave to master to indicate the end of the current step
54   gras_msgtype_declare("dataA", gras_datadesc_by_name("double"));// send data between slave
55   gras_msgtype_declare("dataB", gras_datadesc_by_name("double"));// send data between slave
56 }
57
58 /* Function prototypes */
59 int slave (int argc,char *argv[]);
60 int master (int argc,char *argv[]);
61
62
63 /* **********************************************************************
64  * master code
65  * **********************************************************************/
66
67 /* Global private data */
68 typedef struct {
69   int nbr_col,nbr_row;
70   int remaining_step;
71   int remaining_ack;
72 } master_data_t;
73
74
75 /***  Function initilaze matrixs ***/
76
77 static void initmatrix(matrix_t *X){
78   int i;
79
80   for(i=0 ; i<(X->rows)*(X->cols); i++)
81     X->data[i]=1.0;//*rand()/(RAND_MAX+1.0);
82 } /* end_of_initmatrixs */
83
84 /***  Function Scatter Sequentiel ***/
85
86 static void scatter(){
87
88 }/* end_of_Scatter */
89
90 /***  Function: Scatter // ***/
91
92 static void scatter_parl(){
93
94 }/* end_of_Scatter // */
95
96 /***  Function: multiplication ***/
97
98 static void multiplication(){
99
100 }/* end_of_multiplication */
101
102 /***  Function: gather ***/
103
104 static void gather(){
105
106 }/* end_of_gather */
107
108 /***  Function: Display Matrix ***/
109
110 static void display(matrix_t X){
111         
112   int i,j,t=0;
113
114   printf("      ");
115   for(j=0;j<X.cols;j++)
116     printf("%.3d ",j);
117   printf("\n");
118   printf("    __");
119   for(j=0;j<X.cols;j++)
120     printf("____");
121   printf("_\n");
122
123   for(i=0;i<X.rows;i++){
124     printf("%.3d | ",i);
125     for(j=0;j<X.cols;j++)
126       printf("%.3g ",X.data[t++]);
127     printf("|\n");
128   }
129   printf("    --");
130   for(j=0;j<X.cols;j++)
131     printf("----");
132   printf("-\n");
133
134 }/* end_of_display */
135
136 int master (int argc,char *argv[]) {
137
138   xbt_ex_t e;
139
140   int i,port,ask_result,step;
141
142   matrix_t A,B,C;
143   result_t result;
144
145   gras_socket_t from;
146
147   /*  Init the GRAS's infrastructure */
148   gras_init(&argc, argv);
149
150   gras_socket_t socket[SLAVE_COUNT]; /* sockets for brodcast to slaves */
151
152   /*  Initialize Matrixs */
153
154   A.rows=A.cols=DATA_MATRIX_SIZE;
155   B.rows=B.cols=DATA_MATRIX_SIZE;
156   C.rows=C.cols=DATA_MATRIX_SIZE;
157         
158   A.data=xbt_malloc0(sizeof(double)*DATA_MATRIX_SIZE*DATA_MATRIX_SIZE);
159   B.data=xbt_malloc0(sizeof(double)*DATA_MATRIX_SIZE*DATA_MATRIX_SIZE);
160   C.data=xbt_malloc0(sizeof(double)*DATA_MATRIX_SIZE*DATA_MATRIX_SIZE);
161         
162   initmatrix(&A);
163   initmatrix(&B);
164         
165   /*  Get arguments and create sockets */
166   port=atoi(argv[1]);
167   //scatter();
168   //scatter_parl();
169   //multiplication();
170   //gather();
171   //display(A);
172   /************************* Init Data Send *********************************/
173   int step_ack,j=0;
174   init_data_t mydata;
175   gras_os_sleep(60);      // MODIFIER LES TEMPS D'ATTENTE 60 c trop normalement
176   for( i=2;i< argc;i+=3){
177     TRY {
178       socket[j]=gras_socket_client(argv[i],port);
179     } CATCH(e) {
180       RETHROW0("Unable to connect to the server: %s");
181     }
182     INFO2("Connected to %s:%d.",argv[i],port);
183                 
184     mydata.myrow=atoi(argv[i+1]);  // My row
185     mydata.mycol=atoi(argv[i+2]);  // My column
186                 
187     mydata.a=A.data[(mydata.myrow-1)*PROC_MATRIX_SIZE+(mydata.mycol-1)];
188     mydata.b=B.data[(mydata.myrow-1)*PROC_MATRIX_SIZE+(mydata.mycol-1)];;
189                 
190     gras_msg_send(socket[j],gras_msgtype_by_name("init_data"),&mydata);
191     INFO3("Send Init Data to %s : data A= %.3g & data B= %.3g",
192           gras_socket_peer_name(socket[j]),mydata.a,mydata.b);
193     j++;
194   } // end init Data Send
195
196   /******************************* multiplication ********************************/
197   INFO0("begin Multiplication");
198         
199   for (step=1; step <= PROC_MATRIX_SIZE; step++){
200     gras_os_sleep(50);
201     for (i=0; i< SLAVE_COUNT; i++){
202       TRY {
203         gras_msg_send(socket[i], gras_msgtype_by_name("step"), &step);  /* initialize Mycol, MyRow, mydataA,mydataB*/
204       } CATCH(e) {
205         gras_socket_close(socket[i]);
206         RETHROW0("Unable to send the msg : %s");
207       }
208     }
209     INFO1("send to slave to begin a %d th step",step);
210     /* wait for computing and slave messages exchange */
211     i=0;
212         
213     while  ( i< SLAVE_COUNT){
214       TRY {
215         gras_msg_wait(1300,gras_msgtype_by_name("step_ack"),&from,&step_ack);
216       } CATCH(e) {
217         RETHROW0("I Can't get a Ack step message from slave : %s");
218       }
219       i++;
220       INFO3("Receive Ack step ack from %s (got %d of %d)",
221             gras_socket_peer_name(from),
222             i, SLAVE_COUNT);
223     }
224   }
225   /*********************************  gather ***************************************/
226
227   ask_result=0;
228   for( i=1;i< argc;i++){
229     gras_msg_send(socket[i],gras_msgtype_by_name("ask_result"),&ask_result);
230     INFO1("Send (Ask Result) message to %s",gras_socket_peer_name(socket[i]));
231   }
232   /* wait for results */
233   for( i=1;i< argc;i++){
234     gras_msg_wait(600,gras_msgtype_by_name("result"),&from,&result);
235     C.data[(result.i-1)*DATA_MATRIX_SIZE+(result.j-1)]=result.value;
236   }
237   /*    end of gather   */
238   INFO0 ("The Result of Multiplication is :");
239   display(C);
240
241   return 0;
242 } /* end_of_master */
243
244 /* **********************************************************************
245  * slave code
246  * **********************************************************************/
247
248 int slave(int argc,char *argv[]) {
249
250   xbt_ex_t e; 
251
252   int step,port,l,result_ack=0; 
253   double bA,bB;
254
255   int myrow,mycol;
256   double mydataA,mydataB;
257   double bC=0;
258   
259   //  static end_step;
260
261   result_t result;
262  
263   gras_socket_t from,sock;  /* to recive from server for steps */
264
265   /* sockets for brodcast to other slave */
266   gras_socket_t socket_row[PROC_MATRIX_SIZE-1];
267   gras_socket_t socket_column[PROC_MATRIX_SIZE-1];
268
269   /* Init the GRAS's infrastructure */
270
271   gras_init(&argc, argv);
272
273   /* Get arguments and create sockets */
274
275   port=atoi(argv[1]);
276   
277   /*  Create my master socket */
278   sock = gras_socket_server(port);
279   INFO2("Launch %s (port=%d)",argv[0],port);
280   gras_os_sleep(1); //wait to start all slaves 
281
282   int i;
283   for (i=1;i<PROC_MATRIX_SIZE;i++){
284     socket_row[i-1]=gras_socket_client(argv[i+1],port);
285     socket_column[i-1]=gras_socket_client(argv[i+PROC_MATRIX_SIZE],port);
286   }
287
288   /*  Register the known messages */
289   register_messages();
290
291   /* Recover my initialized Data and My Position*/
292   init_data_t mydata;
293   INFO0("wait for init Data");
294   TRY {
295     gras_msg_wait(600,gras_msgtype_by_name("init_data"),&from,&mydata);
296   } CATCH(e) {
297     RETHROW0("I Can't get a init Data message from master : %s");
298   }
299   myrow=mydata.myrow;
300   mycol=mydata.mycol;
301   mydataA=mydata.a;
302   mydataB=mydata.b;
303   INFO4("Recive MY POSITION (%d,%d) and MY INIT DATA ( A=%.3g | B=%.3g )",
304         myrow,mycol,mydataA,mydataB);
305   step=1;
306   
307   do {  //repeat until compute Cb
308     step=PROC_MATRIX_SIZE+1;  // just intilization for loop
309         
310     TRY {
311       gras_msg_wait(200,gras_msgtype_by_name("step"),&from,&step);
312     } CATCH(e) {
313       RETHROW0("I Can't get a Next Step message from master : %s");
314     }
315     INFO1("Recive a step message from master: step = %d ",step);
316
317     if (step < PROC_MATRIX_SIZE ){
318       /* a row brodcast */
319       gras_os_sleep(3);  // IL FAUT EXPRIMER LE TEMPS D'ATTENTE EN FONCTION DE "SLAVE_COUNT"
320       if(myrow==step){
321         INFO2("step(%d) = Myrow(%d)",step,myrow);
322         for (l=1;l < PROC_MATRIX_SIZE ;l++){
323           gras_msg_send(socket_column[l-1], gras_msgtype_by_name("dataB"), &mydataB);
324           bB=mydataB;
325           INFO1("send my data B (%.3g) to my (vertical) neighbors",bB);  
326         }
327       }
328       if(myrow != step){ 
329         INFO2("step(%d) <> Myrow(%d)",step,myrow);
330         TRY {
331           gras_msg_wait(600,gras_msgtype_by_name("dataB"),
332                         &from,&bB);
333         } CATCH(e) {
334           RETHROW0("I Can't get a data message from row : %s");
335         }
336         INFO2("Recive data B (%.3g) from my neighbor: %s",bB,gras_socket_peer_name(from));
337       }
338       /* a column brodcast */
339       if(mycol==step){
340         for (l=1;l < PROC_MATRIX_SIZE ;l++){
341           gras_msg_send(socket_row[l-1],gras_msgtype_by_name("dataA"), &mydataA);
342           bA=mydataA;
343           INFO1("send my data A (%.3g) to my (horizontal) neighbors",bA);
344         }
345       }
346
347       if(mycol != step){
348         TRY {
349           gras_msg_wait(1200,gras_msgtype_by_name("dataA"),
350                         &from,&bA);
351         } CATCH(e) {
352           RETHROW0("I Can't get a data message from column : %s");
353         }
354         INFO2("Recive data A (%.3g) from my neighbor : %s ",bA,gras_socket_peer_name(from));
355       }
356       bC+=bA*bB;
357       INFO1(">>>>>>>> My BC = %.3g",bC);
358
359       /* send a ack msg to master */
360         
361       gras_msg_send(from,gras_msgtype_by_name("step_ack"),&step);
362         
363       INFO1("Send ack to master for to end %d th step",step);
364     }
365     if(step==PROC_MATRIX_SIZE-1) break;
366         
367   } while (step < PROC_MATRIX_SIZE);
368   /*  wait Message from master to send the result */
369  
370   result.value=bC;
371   result.i=myrow;
372   result.j=mycol;
373  
374   TRY {
375     gras_msg_wait(600,gras_msgtype_by_name("ask_result"),
376                   &from,&result_ack);
377   } CATCH(e) {
378     RETHROW0("I Can't get a data message from row : %s");
379   }
380   /* send Result to master */
381   TRY {
382     gras_msg_send(from, gras_msgtype_by_name("result"),&result);
383   } CATCH(e) {
384     // gras_socket_close(from);
385     RETHROW0("Failed to send PING to server: %s");
386   }
387   INFO3(">>>>>>>> Result: %.3f sent to %s:%d <<<<<<<<",
388         bC,
389         gras_socket_peer_name(from),gras_socket_peer_port(from));
390   /*  Free the allocated resources, and shut GRAS down */
391   gras_socket_close(from);
392   gras_exit();
393   INFO0("Done.");
394   return 0;
395 } /* end_of_slave */