2 /* pmm - parallel matrix multiplication "double diffusion" */
4 /* Copyright (c) 2006- Ahmed Harbaoui. All rights reserved. */
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. */
10 #define PROC_MATRIX_SIZE 3
11 #define SLAVE_COUNT (PROC_MATRIX_SIZE*PROC_MATRIX_SIZE)
13 #define DATA_MATRIX_SIZE 3
15 XBT_LOG_NEW_DEFAULT_CATEGORY(pmm,"Parallel Matrix Multiplication");
17 GRAS_DEFINE_TYPE(s_matrix,struct s_matrix {
20 double *data GRAS_ANNOTE(size, lines*rows);
22 typedef struct s_matrix matrix_t;
24 /* struct for recovering results */
25 GRAS_DEFINE_TYPE(s_result,struct s_result {
30 typedef struct s_result result_t;
32 /* struct to send initial data to slave */
33 GRAS_DEFINE_TYPE(s_init_data,struct s_init_data {
39 typedef struct s_init_data init_data_t;
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);
48 gras_msgtype_declare("result", result_type); // receive a final result from slave
49 gras_msgtype_declare("init_data", init_data_type); // send from master to slave to initialize data bA,bB
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
58 /* Function prototypes */
59 int slave (int argc,char *argv[]);
60 int master (int argc,char *argv[]);
63 /* **********************************************************************
65 * **********************************************************************/
67 /* Global private data */
75 /*** Function initilaze matrixs ***/
77 static void initmatrix(matrix_t *X){
80 for(i=0 ; i<(X->lines)*(X->rows); i++)
81 X->data[i]=1.0;//*rand()/(RAND_MAX+1.0);
82 } /* end_of_initmatrixs */
84 /*** Function Scatter Sequentiel ***/
86 static void scatter(){
90 /*** Function: Scatter // ***/
92 static void scatter_parl(){
94 }/* end_of_Scatter // */
96 /*** Function: multiplication ***/
98 static void multiplication(){
100 }/* end_of_multiplication */
102 /*** Function: gather ***/
104 static void gather(){
108 /*** Function: Display Matrix ***/
110 static void display(matrix_t X){
115 for(j=0;j<X.rows;j++)
119 for(j=0;j<X.rows;j++)
123 for(i=0;i<X.lines;i++){
125 for(j=0;j<X.rows;j++)
126 printf("%.3g ",X.data[t++]);
130 for(j=0;j<X.rows;j++)
134 }/* end_of_display */
136 int master (int argc,char *argv[]) {
140 int i,port,ask_result,step;
147 /* Init the GRAS's infrastructure */
148 gras_init(&argc, argv);
150 gras_socket_t socket[SLAVE_COUNT]; /* sockets for brodcast to slaves */
152 /* Initialize Matrixs */
154 A.lines=A.rows=DATA_MATRIX_SIZE;
155 B.lines=B.rows=DATA_MATRIX_SIZE;
156 C.lines=C.rows=DATA_MATRIX_SIZE;
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);
165 /* Get arguments and create sockets */
172 /************************* Init Data Send *********************************/
175 gras_os_sleep(60); // MODIFIER LES TEMPS D'ATTENTE 60 c trop normalement
178 for( i=2;i< argc;i++){
180 socket[j]=gras_socket_client(argv[i],port);
182 RETHROW0("Unable to connect to the server: %s");
184 INFO2("Connected to %s:%d.",argv[i],port);
186 mydata.myline=line; // My line
187 mydata.myrow=row; // My row
189 if (line > PROC_MATRIX_SIZE) {
194 mydata.a=A.data[(mydata.myline-1)*PROC_MATRIX_SIZE+(mydata.myrow-1)];
195 mydata.b=B.data[(mydata.myline-1)*PROC_MATRIX_SIZE+(mydata.myrow-1)];;
197 gras_msg_send(socket[j],gras_msgtype_by_name("init_data"),&mydata);
198 INFO3("Send Init Data to %s : data A= %.3g & data B= %.3g",
199 gras_socket_peer_name(socket[j]),mydata.a,mydata.b);
202 // end init Data Send
204 /******************************* multiplication ********************************/
205 INFO0("XXXXXXXXXXXXXXXXXXXXXX begin Multiplication");
207 for (step=1; step <= PROC_MATRIX_SIZE; step++){
208 // gras_os_sleep(50);
209 for (i=0; i< SLAVE_COUNT; i++){
211 gras_msg_send(socket[i], gras_msgtype_by_name("step"), &step);
213 gras_socket_close(socket[i]);
214 RETHROW0("Unable to send the msg : %s");
217 INFO1("send to slave to begin a %d th step",step);
218 /* wait for computing and slave messages exchange */
221 while ( i< SLAVE_COUNT){
223 gras_msg_wait(1300,gras_msgtype_by_name("step_ack"),&from,&step_ack);
225 RETHROW0("I Can't get a Ack step message from slave : %s");
228 INFO3("Receive Ack step ack from %s (got %d of %d)",
229 gras_socket_peer_name(from),
233 /********************************* gather ***************************************/
236 for( i=1;i< argc;i++){
237 gras_msg_send(socket[i],gras_msgtype_by_name("ask_result"),&ask_result);
238 INFO1("Send (Ask Result) message to %s",gras_socket_peer_name(socket[i]));
240 /* wait for results */
241 for( i=1;i< argc;i++){
242 gras_msg_wait(600,gras_msgtype_by_name("result"),&from,&result);
243 C.data[(result.i-1)*DATA_MATRIX_SIZE+(result.j-1)]=result.value;
246 INFO0 ("The Result of Multiplication is :");
250 } /* end_of_master */
252 /* **********************************************************************
254 * **********************************************************************/
256 int slave(int argc,char *argv[]) {
260 int step,port,l,result_ack=0;
264 double mydataA,mydataB;
271 gras_socket_t from,sock; /* to receive from server for steps */
273 /* sockets for brodcast to other slave */
274 gras_socket_t socket_line[PROC_MATRIX_SIZE-1];
275 gras_socket_t socket_row[PROC_MATRIX_SIZE-1];
277 /* Init the GRAS's infrastructure */
279 gras_init(&argc, argv);
281 /* Get arguments and create sockets */
285 /* Create my master socket */
286 sock = gras_socket_server(port);
287 INFO2("Launch %s (port=%d)",argv[0],port);
288 gras_os_sleep(1); //wait to start all slaves
291 for (i=1;i<PROC_MATRIX_SIZE;i++){
292 socket_line[i-1]=gras_socket_client(argv[i+1],port);
293 socket_row[i-1]=gras_socket_client(argv[i+PROC_MATRIX_SIZE],port);
296 /* Register the known messages */
299 /* Recover my initialized Data and My Position*/
301 INFO0("wait for init Data");
303 gras_msg_wait(600,gras_msgtype_by_name("init_data"),&from,&mydata);
305 RETHROW0("I Can't get a init Data message from master : %s");
307 myline=mydata.myline;
311 INFO4("Receive MY POSITION (%d,%d) and MY INIT DATA ( A=%.3g | B=%.3g )",
312 myline,myrow,mydataA,mydataB);
315 do { //repeat until compute Cb
316 step=PROC_MATRIX_SIZE+1; // just intilization for loop
319 gras_msg_wait(200,gras_msgtype_by_name("step"),&from,&step);
321 RETHROW0("I Can't get a Next Step message from master : %s");
323 INFO1("Receive a step message from master: step = %d ",step);
325 if (step < PROC_MATRIX_SIZE ){
326 /* a line brodcast */
327 gras_os_sleep(3); // IL FAUT EXPRIMER LE TEMPS D'ATTENTE EN FONCTION DE "SLAVE_COUNT"
329 INFO2("step(%d) = Myline(%d)",step,myline);
330 for (l=1;l < PROC_MATRIX_SIZE ;l++){
331 gras_msg_send(socket_row[l-1], gras_msgtype_by_name("dataB"), &mydataB);
333 INFO1("send my data B (%.3g) to my (vertical) neighbors",bB);
337 INFO2("step(%d) <> Myline(%d)",step,myline);
339 gras_msg_wait(600,gras_msgtype_by_name("dataB"),
342 RETHROW0("I Can't get a data message from line : %s");
344 INFO2("Receive data B (%.3g) from my neighbor: %s",bB,gras_socket_peer_name(from));
348 for (l=1;l < PROC_MATRIX_SIZE ;l++){
349 gras_msg_send(socket_line[l-1],gras_msgtype_by_name("dataA"), &mydataA);
351 INFO1("send my data A (%.3g) to my (horizontal) neighbors",bA);
357 gras_msg_wait(1200,gras_msgtype_by_name("dataA"),
360 RETHROW0("I Can't get a data message from row : %s");
362 INFO2("Receive data A (%.3g) from my neighbor : %s ",bA,gras_socket_peer_name(from));
365 INFO1(">>>>>>>> My BC = %.3g",bC);
367 /* send a ack msg to master */
369 gras_msg_send(from,gras_msgtype_by_name("step_ack"),&step);
371 INFO1("Send ack to master for to end %d th step",step);
373 if(step==PROC_MATRIX_SIZE-1) break;
375 } while (step < PROC_MATRIX_SIZE);
376 /* wait Message from master to send the result */
383 gras_msg_wait(600,gras_msgtype_by_name("ask_result"),
386 RETHROW0("I Can't get a data message from line : %s");
388 /* send Result to master */
390 gras_msg_send(from, gras_msgtype_by_name("result"),&result);
392 // gras_socket_close(from);
393 RETHROW0("Failed to send PING to server: %s");
395 INFO3(">>>>>>>> Result: %.3f sent to %s:%d <<<<<<<<",
397 gras_socket_peer_name(from),gras_socket_peer_port(from));
398 /* Free the allocated resources, and shut GRAS down */
399 gras_socket_close(from);