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, rows*cols);
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); // 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
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->rows)*(X->cols); 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.cols;j++)
119 for(j=0;j<X.cols;j++)
123 for(i=0;i<X.rows;i++){
125 for(j=0;j<X.cols;j++)
126 printf("%.3g ",X.data[t++]);
130 for(j=0;j<X.cols;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.rows=A.cols=DATA_MATRIX_SIZE;
155 B.rows=B.cols=DATA_MATRIX_SIZE;
156 C.rows=C.cols=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
176 for( i=2;i< argc;i+=3){
178 socket[j]=gras_socket_client(argv[i],port);
180 RETHROW0("Unable to connect to the server: %s");
182 INFO2("Connected to %s:%d.",argv[i],port);
184 mydata.myrow=atoi(argv[i+1]); // My row
185 mydata.mycol=atoi(argv[i+2]); // My column
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)];;
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);
194 } // end init Data Send
196 /******************************* multiplication ********************************/
197 INFO0("begin Multiplication");
199 for (step=1; step <= PROC_MATRIX_SIZE; step++){
201 for (i=0; i< SLAVE_COUNT; i++){
203 gras_msg_send(socket[i], gras_msgtype_by_name("step"), &step); /* initialize Mycol, MyRow, mydataA,mydataB*/
205 gras_socket_close(socket[i]);
206 RETHROW0("Unable to send the msg : %s");
209 INFO1("send to slave to begin a %d th step",step);
210 /* wait for computing and slave messages exchange */
213 while ( i< SLAVE_COUNT){
215 gras_msg_wait(1300,gras_msgtype_by_name("step_ack"),&from,&step_ack);
217 RETHROW0("I Can't get a Ack step message from slave : %s");
220 INFO3("Receive Ack step ack from %s (got %d of %d)",
221 gras_socket_peer_name(from),
225 /********************************* gather ***************************************/
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]));
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;
238 INFO0 ("The Result of Multiplication is :");
242 } /* end_of_master */
244 /* **********************************************************************
246 * **********************************************************************/
248 int slave(int argc,char *argv[]) {
252 int step,port,l,result_ack=0;
256 double mydataA,mydataB;
263 gras_socket_t from,sock; /* to recive from server for steps */
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];
269 /* Init the GRAS's infrastructure */
271 gras_init(&argc, argv);
273 /* Get arguments and create sockets */
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
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);
288 /* Register the known messages */
291 /* Recover my initialized Data and My Position*/
293 INFO0("wait for init Data");
295 gras_msg_wait(600,gras_msgtype_by_name("init_data"),&from,&mydata);
297 RETHROW0("I Can't get a init Data message from master : %s");
303 INFO4("Recive MY POSITION (%d,%d) and MY INIT DATA ( A=%.3g | B=%.3g )",
304 myrow,mycol,mydataA,mydataB);
307 do { //repeat until compute Cb
308 step=PROC_MATRIX_SIZE+1; // just intilization for loop
311 gras_msg_wait(200,gras_msgtype_by_name("step"),&from,&step);
313 RETHROW0("I Can't get a Next Step message from master : %s");
315 INFO1("Recive a step message from master: step = %d ",step);
317 if (step < PROC_MATRIX_SIZE ){
319 gras_os_sleep(3); // IL FAUT EXPRIMER LE TEMPS D'ATTENTE EN FONCTION DE "SLAVE_COUNT"
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);
325 INFO1("send my data B (%.3g) to my (vertical) neighbors",bB);
329 INFO2("step(%d) <> Myrow(%d)",step,myrow);
331 gras_msg_wait(600,gras_msgtype_by_name("dataB"),
334 RETHROW0("I Can't get a data message from row : %s");
336 INFO2("Recive data B (%.3g) from my neighbor: %s",bB,gras_socket_peer_name(from));
338 /* a column brodcast */
340 for (l=1;l < PROC_MATRIX_SIZE ;l++){
341 gras_msg_send(socket_row[l-1],gras_msgtype_by_name("dataA"), &mydataA);
343 INFO1("send my data A (%.3g) to my (horizontal) neighbors",bA);
349 gras_msg_wait(1200,gras_msgtype_by_name("dataA"),
352 RETHROW0("I Can't get a data message from column : %s");
354 INFO2("Recive data A (%.3g) from my neighbor : %s ",bA,gras_socket_peer_name(from));
357 INFO1(">>>>>>>> My BC = %.3g",bC);
359 /* send a ack msg to master */
361 gras_msg_send(from,gras_msgtype_by_name("step_ack"),&step);
363 INFO1("Send ack to master for to end %d th step",step);
365 if(step==PROC_MATRIX_SIZE-1) break;
367 } while (step < PROC_MATRIX_SIZE);
368 /* wait Message from master to send the result */
375 gras_msg_wait(600,gras_msgtype_by_name("ask_result"),
378 RETHROW0("I Can't get a data message from row : %s");
380 /* send Result to master */
382 gras_msg_send(from, gras_msgtype_by_name("result"),&result);
384 // gras_socket_close(from);
385 RETHROW0("Failed to send PING to server: %s");
387 INFO3(">>>>>>>> Result: %.3f sent to %s:%d <<<<<<<<",
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);