c1ebecf53ba04e8e3db783f0be1a0d3d2b5c9c73
[charm.git] / tests / charm++ / commtest / eachtomany / eachtomany.C
1
2 #include <comlib.h>
3 #include <cassert>
4 #include <iostream>
5
6 #include "eachtomany.decl.h"
7
8
9 /*
10  * Test of EachToMany Strategy
11  * 
12  * We perform multiple tests. Each test uses its own array and strategy instance. 
13  * All arrays are the same size.
14  * 
15  * Tests:
16  *    1) Migrate a single element around the ring of PEs
17  *    2) Different source and destination arrays
18  *    3) Migrating objects in various ways, leaving some PEs with no objects
19  *   
20  *    4) Random Migrations of source and destination arrays <disabled>
21  * 
22  *    5) Random Migrations same source and destination <unimplemented so far>
23  * 
24  */
25
26 CProxy_Main mainProxy;
27
28 CProxy_EachToManyArray testProxy1;
29 CProxy_EachToManyArray testProxy2src;
30 CProxy_EachToManyArray testProxy2dest;
31 CProxy_EachToManyArray testProxy3;
32 CProxy_EachToManyArray testProxy4src;
33 CProxy_EachToManyArray testProxy4dest;
34
35 ComlibInstanceHandle testStrategy1;
36 ComlibInstanceHandle testStrategy2;
37 ComlibInstanceHandle testStrategy3;
38 ComlibInstanceHandle testStrategy4;
39
40
41 #define DEBUG 0
42 #define COMMDEBUG 0
43
44 class eachToManyMessage : public CMessage_eachToManyMessage{
45 public:
46   int length;
47   char* msg;
48 };
49
50 class Main : public CBase_Main
51 {
52 private:
53
54   int nDone1;
55   int nDone2;
56   int nDone3;
57   int nDone4;
58   int totalIterations;
59   int iter1;
60   int iter2;
61   int iter3;
62   int iter4;
63   int numCompletedTests;
64   int numtests;
65   int numsetup;
66   int nElements;
67   
68   /// The number of array elements that have reported their successful setup so far
69   int nArrElemSetup;
70   
71
72   char *test3Counts;
73
74 public:
75
76   Main(CkArgMsg *m) {    
77     nDone1 = 0;
78     nDone2 = 0;
79     nDone3 = 0;
80     nDone4 = 0;
81     numCompletedTests = 0;
82     totalIterations = 20;
83     iter1 = 0;
84     iter2 = 0;
85     iter3 = 0;
86     iter4 = 0;
87     nArrElemSetup = 0;    
88     nElements = 20;
89     mainProxy = thishandle;
90     numsetup=0;
91     numtests=0;
92     
93     srand(1);
94     
95     com_debug = COMMDEBUG; // also below
96         
97     // Create the arrays
98     testProxy1 = CProxy_EachToManyArray::ckNew(nElements);
99     testProxy2src = CProxy_EachToManyArray::ckNew(nElements);
100     testProxy2dest = CProxy_EachToManyArray::ckNew(nElements);
101     testProxy3 = CProxy_EachToManyArray::ckNew(nElements);
102     testProxy4src = CProxy_EachToManyArray::ckNew(nElements);
103     testProxy4dest = CProxy_EachToManyArray::ckNew(nElements);
104     
105     
106     CkArrayIndex *allElts = new CkArrayIndex[nElements];
107     for (int i = 0; i<nElements; i++) {
108         CkArrayIndex1D index = i;
109         allElts[i] = index;
110     }
111     
112     Strategy *strategy;
113     
114     strategy = new EachToManyMulticastStrategy(USE_DIRECT, testProxy1, testProxy1, nElements,allElts,nElements,allElts);
115     testStrategy1 = ComlibRegister(strategy);
116     
117     strategy = new EachToManyMulticastStrategy(USE_DIRECT, testProxy2src, testProxy2dest, nElements,allElts,nElements,allElts);
118     testStrategy2 = ComlibRegister(strategy);
119     
120     strategy = new EachToManyMulticastStrategy(USE_DIRECT, testProxy3, testProxy3, nElements,allElts,nElements,allElts);
121     testStrategy3 = ComlibRegister(strategy);
122
123     strategy = new EachToManyMulticastStrategy(USE_DIRECT, testProxy4src, testProxy4dest, nElements,allElts,nElements,allElts);
124     testStrategy4 = ComlibRegister(strategy);
125     
126     delete [] allElts;
127  
128     test3Counts = new char[nElements*nElements];
129     for(int i=0;i<nElements*nElements;i++)
130       test3Counts[i] = 0;
131
132     testProxy1.setup(testStrategy1);     numsetup++;
133     testProxy2src.setup(testStrategy2);  numsetup++;
134     testProxy2dest.setup(testStrategy2); numsetup++;
135     testProxy3.setup(testStrategy3);     numsetup++;
136     testProxy4src.setup(testStrategy4);  numsetup++;
137     testProxy4dest.setup(testStrategy4); numsetup++;
138       
139   } 
140
141   void arraySetupDone(){
142            nArrElemSetup ++;
143            int numElementsToSetup = nElements*numsetup;
144 #if DEBUG
145            CkPrintf("Setup %d/%d\n", nArrElemSetup, numElementsToSetup);
146 #endif
147            if(nArrElemSetup == numElementsToSetup){
148
149 #if QDSTARTUP
150              CkCallback *cbstart = new CkCallback(CkIndex_Main::startTests(), thisProxy);
151              CkStartQD(*cbstart);
152 #else
153              startTests();
154 #endif
155
156            }
157   }
158    
159
160   void startTests(){
161     numtests = 0;
162     testProxy1.test1(iter1); CkPrintf("Running test 1\n"); numtests++;
163     testProxy2src.test2(iter2); CkPrintf("Running test 2\n"); numtests++;
164     testProxy3.test3(iter3);  CkPrintf("Running test 3\n"); numtests++;
165     testProxy4src.test4(iter4); CkPrintf("Running test 4\n"); numtests++;
166   }
167
168   
169   void testComplete(int whichTest){
170           CkPrintf("Test #%d completed successfully\n", whichTest, numtests);
171           fflush(stdout);
172
173           numCompletedTests ++;
174            
175           if(numCompletedTests == numtests)
176                   CkExit();
177
178   }
179   
180   
181   void next1(){
182           nDone1++;
183           
184 #if DEBUG
185           CkPrintf("[MainChare] Test 1 doNext()  nDone=%d\n", nDone1); 
186           fflush(stdout);
187 #endif
188           
189           // Becase each array element sends a message to all array elements, there are a total of nElements^2 messages received
190           const int nTotal = nElements*nElements;
191           if (nDone1 == nTotal){
192 #if DEBUG
193             CkPrintf("[MainChare] Test 1 Completed iteration %d\n",iter1);
194             fflush(stdout);
195 #endif
196                   iter1 ++;
197                   nDone1 = 0;
198                   if(iter1 == totalIterations){
199                           testComplete(1);
200                   } else {
201
202                           // Do another iteration
203                           int arrElt = 2;
204                           int numPes = CkNumPes();
205                           int destPe = iter1%numPes;
206
207                           if( iter1>4 && arrElt<nElements && destPe < CkNumPes() ){
208 #if DEBUG
209                                   CkPrintf("[%d] Test 1 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), arrElt, destPe, iter1, numPes);
210 #endif
211                                   testProxy1[arrElt].migrateMeTo(destPe);
212                           } 
213                           testProxy1.test1(iter1);
214
215                   }
216           }    
217   }
218   
219   
220   void next2(){
221           nDone2++;
222
223           // Becase each array element sends a message to all array elements, there are a total of nElements^2 messages received
224           const int nTotal = nElements*nElements;
225           if (nDone2 == nTotal){
226 #if DEBUG
227                   CkPrintf("[MainChare] Test 2 Completed iteration %d\n",iter2);
228 #endif
229                   iter2 ++;
230                   nDone2 = 0;
231                   if(iter2 == totalIterations){
232                           testComplete(2);
233                   } else {
234                           // Do another iteration
235                           testProxy2src.test2(iter2);
236                   }
237           }    
238   }
239
240
241   void next3(int srcElt, int srcPE, int destElt, int destPE){ 
242           nDone3++; 
243 #if DEBUG
244           CkPrintf("[MainChare] next3 iter=%d srcElt=%d srcPe=%d destElt=%d destPe=%d nDone3=%d\n", iter3, srcElt, srcPE,destElt, destPE, nDone3);
245           fflush(stdout);
246 #endif
247
248           if(test3Counts[nElements*destElt+srcElt]!=0){
249             CkPrintf("next3 received more than one message for destElt=%d srcElt=%d\n", destElt, srcElt);
250             CkAbort("test3Counts[nElements*destElt+srcElt]!=0");
251           }
252           test3Counts[nElements*destElt+srcElt] ++;
253           
254           // Becase each array element sends a message to all array elements, there are a total of nElements^2 messages received 
255           const int nTotal = nElements*nElements; 
256           if (nDone3 == nTotal){ 
257 #if DEBUG
258                   CkPrintf("[MainChare] Test 3 Completed iteration %d\n",iter3); 
259           fflush(stdout);
260 #endif
261
262           
263           for(int i=0;i<nElements*nElements;i++)
264             test3Counts[i] = 0;
265
266
267                   iter3 ++; 
268                   nDone3 = 0; 
269                   if(iter3 == totalIterations){ 
270                           testComplete(3); 
271                   } else { 
272                           // Do another iteration 
273
274                           int numPes = CkNumPes();
275                           int destPe;
276
277 #if 0
278                           // Have all objects migrate to PE 1
279                           destPe = 1;
280                           if( iter3==3 && numPes>1 && destPe<numPes){ 
281                                   for(int e=0; e<nElements; e++){
282 #if DEBUG
283                                           CkPrintf("[%d] Test 3 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), e, destPe, iter3, numPes); 
284                                           fflush(stdout);
285 #endif
286                                           testProxy3[e].migrateMeTo(destPe); 
287                                   }
288                           }     
289
290                           // Have all objects migrate to PE 2
291                           destPe = 2;
292                           if( iter3==6 && numPes>1 && destPe<numPes){ 
293                                   for(int e=0; e<nElements; e++){
294 #if DEBUG
295                                           CkPrintf("[%d] Test 3 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), e, destPe, iter3, numPes); 
296                                           fflush(stdout);
297 #endif
298                                           testProxy3[e].migrateMeTo(destPe); 
299                                   }
300                           }
301
302                           // Have all objects migrate to PE 0
303                           destPe = 0;
304                           if( iter3==9 && numPes>1 && destPe<numPes){ 
305                                   for(int e=0; e<nElements; e++){
306 #if DEBUG
307                                           CkPrintf("[%d] Test 3 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), e, destPe, iter3, numPes); 
308                                           fflush(stdout);
309 #endif
310                                           testProxy3[e].migrateMeTo(destPe); 
311                                   }
312                           }
313                           
314
315                           // Migrate back to all PEs
316                           if( iter3==10){ 
317                                   for(int e=0; e<nElements; e++){
318                                           destPe= (e+3) % CkNumPes();
319                                           if(destPE < CkNumPes()){
320 #if DEBUG
321                                             CkPrintf("[%d] Test 3 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), e, destPe, iter3, numPes); 
322                                             fflush(stdout);
323 #endif
324                                             
325                                             testProxy3[e].migrateMeTo(destPe); 
326                                           }
327                                   }
328                           }
329
330 #endif
331                           
332                           
333                           // Migrate half to PE1 and half to PE2
334                           if( iter3==12 && numPes>2){ 
335                                   for(int e=0; e<nElements; e++){
336                                           destPe= e % 2 + 1;
337 #if DEBUG
338                                           CkPrintf("[%d] Test 3 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), e, destPe, iter3, numPes); 
339                                           fflush(stdout);
340 #endif
341                                           testProxy3[e].migrateMeTo(destPe); 
342                                   }
343                           }
344
345
346                           // Migrate half to PE0 and half to PE1
347                           if( iter3==14 && numPes>2){ 
348                                   for(int e=0; e<nElements; e++){
349                                           destPe= e % 2;
350                                           
351                                           if(destPE < CkNumPes()){
352
353 #if DEBUG
354                                             CkPrintf("[%d] Test 3 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), e, destPe, iter3, numPes); 
355                                             fflush(stdout);
356 #endif
357                                             testProxy3[e].migrateMeTo(destPe); 
358                                           }
359                                   }
360                           }
361
362
363                                 
364                           // Migrate back to all PEs
365                           if( iter3==16 ){ 
366                                   for(int e=0; e<nElements; e++){
367                                           destPe= e % CkNumPes();
368                                           if(destPE < CkNumPes()){
369
370 #if DEBUG
371                                             CkPrintf("[%d] Test 3 Decided to migrate elt %d to %d iter=%d numpes=%d\n", CkMyPe(), e, destPe, iter3, numPes); 
372                                             fflush(stdout);
373 #endif
374                                             testProxy3[e].migrateMeTo(destPe); 
375                                           }
376                                   }
377                           }
378
379 #if DEBUG                                               
380                           CkPrintf("[%d] Test 3 continuing on to iteration %d\n", CkMyPe(), iter3); 
381                           fflush(stdout);
382 #endif
383                           testProxy3.test3(iter3); 
384                   } 
385           }     
386   } 
387   
388   
389   
390   
391   
392   
393   void next4(){
394           nDone4++;
395 //        CkPrintf("[MainChare] Test 4 nDone4=%d\n",nDone4);
396
397           // Becase each array element sends a message to all array elements, there are a total of nElements^2 messages received
398           const int nTotal = nElements*nElements;
399           if (nDone4 == nTotal){
400                   ComlibPrintf("[MainChare] Test 4 Completed iteration %d\n",iter4);
401
402                   iter4 ++;
403                   nDone4 = 0;
404                   if(iter4 == totalIterations){
405                           testComplete(4);
406                   } else {
407                           // Do another iteration
408
409                           int numToMigrate = 4;
410                           int numPes = CkNumPes();
411                           
412                           // Migrate back to all PEs
413                           for(int i=0;i<numToMigrate;i++){
414                                   int e = rand() % nElements;
415                                   int destPe= rand() % numPes;
416                                   
417 //                                CkPrintf("[%d] Test 4 randomly decided to migrate src elt %d to %d iter=%d\n", CkMyPe(), e, destPe, iter4); 
418 //                                testProxy4src[e].migrateMeTo(destPe); 
419
420 //                                int e2 = rand() % nElements;
421 //                                int destPe2= rand() % numPes;
422 //
423 //                                CkPrintf("[%d] Test 4 randomly decided to migrate dest elt %d to %d iter=%d\n", CkMyPe(), e2, destPe2, iter4); 
424 //                                testProxy4dest[e2].migrateMeTo(destPe2); 
425
426                                   
427                           }
428
429
430                           testProxy4src.test4(iter4);
431                   }
432           }    
433   }
434
435   
436   
437   
438   
439   
440 };
441
442
443
444 class EachToManyArray : public CBase_EachToManyArray {
445 private:
446   CProxy_EachToManyArray myDelegatedProxy;
447   ComlibInstanceHandle cinst;
448   
449 public:
450
451   EachToManyArray() {
452           com_debug = COMMDEBUG; // also above
453   }
454
455   void pup(PUP::er &p){
456           p | cinst;
457           if(p.isUnpacking()){
458                   myDelegatedProxy = thisProxy;
459                   ComlibAssociateProxy(cinst, myDelegatedProxy);
460           }
461   }
462
463   
464   EachToManyArray(CkMigrateMessage *m) {
465 #if DEBUG
466           CkPrintf("Object %d has migrated to %d\n", thisIndex, CkMyPe());
467           fflush(stdout);
468 #endif
469   }
470   
471   void setup(ComlibInstanceHandle inst){
472           // We cannot put this in the constructor because the strategy may not yet have been created. Our references to it would therefore be invald.
473           cinst = inst;
474           myDelegatedProxy = thisProxy;
475           ComlibAssociateProxy(cinst, myDelegatedProxy); 
476           mainProxy.arraySetupDone();
477   }
478   
479   
480   void migrateMeTo(int toPe){
481           migrateMe (toPe);
482   }
483   
484     
485   void test1(int iter) {
486 #if DEBUG
487     CkPrintf("[%d] test1 iter=%d thisIndex=%d\n", CkMyPe(), iter, thisIndex);
488     fflush(stdout);
489 #endif
490     
491     // Build a message
492     char *msg = (char*)malloc(256);
493     sprintf(msg, "%d %d %d", thisIndex, CkMyPe(), iter); 
494     eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage;
495     memcpy(b->msg, msg, strlen(msg)+1);
496     b->length = strlen(msg);
497     // Broadcast the message to the whole array
498     ComlibBegin(myDelegatedProxy, iter);
499     myDelegatedProxy.receive1(b);
500     ComlibEnd(myDelegatedProxy, iter);
501     // Free the message
502     free(msg);
503   }
504
505    
506   void test2(int iter) {
507           // Build a message
508           char *msg = (char*)malloc(256);
509           sprintf(msg, "%d", thisIndex);
510           eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage;
511           memcpy(b->msg, msg, strlen(msg)+1);
512           b->length = strlen(msg);
513           // Broadcast the message to the whole array
514           ComlibBegin(myDelegatedProxy, iter);
515           myDelegatedProxy.receive2(b);
516           ComlibEnd(myDelegatedProxy, iter);
517           // Free the message
518           free(msg);
519   }
520
521
522   void test3(int iter) { 
523 #if DEBUG
524     CkPrintf("[%d] test3 iter=%d thisIndex=%d\n", CkMyPe(), iter, thisIndex);
525     fflush(stdout);
526 #endif
527
528           // Build a message 
529           char *msg = (char*)malloc(256); 
530           sprintf(msg, "%d %d %d", thisIndex, CkMyPe(), iter); 
531           eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage; 
532           memcpy(b->msg, msg, strlen(msg)+1); 
533           b->length = strlen(msg); 
534           // Broadcast the message to the whole array 
535           ComlibBegin(myDelegatedProxy, iter); 
536           myDelegatedProxy.receive3(b); 
537           ComlibEnd(myDelegatedProxy, iter); 
538           // Free the message 
539           free(msg); 
540   } 
541  
542   void test4(int iter) {
543           // Build a message
544           char *msg = (char*)malloc(256);
545           sprintf(msg, "%d", thisIndex);
546           eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage;
547           memcpy(b->msg, msg, strlen(msg)+1);
548           b->length = strlen(msg);
549           // Broadcast the message to the whole array
550           ComlibBegin(myDelegatedProxy, iter);
551           myDelegatedProxy.receive4(b);
552           ComlibEnd(myDelegatedProxy, iter);
553           // Free the message
554           free(msg);
555    }
556
557
558   
559   void receive1(eachToManyMessage* m) {      
560     int srcElt, srcPE, destPE, iter;
561     sscanf(m->msg,"%d %d %d",&srcElt, &srcPE, &iter);
562     delete m; 
563 #if DEBUG
564     CkPrintf("[%d] receive1 from srcElt=%d srcPE=%d iter=%d thisElt=%d\n", CkMyPe(), srcElt, srcPE, iter, thisIndex);
565     fflush(stdout);
566 #endif
567     mainProxy.next1();
568   }
569   
570   
571
572   void receive2(eachToManyMessage* m) {
573 //#if DEBUG
574 //  //    CkPrintf("[%d] Application: received message %s\n", CkMyPe(), m->msg);
575 //    int src;
576 //    sscanf(m->msg,"%d",&src);
577 //    CkPrintf("Test 2 Received: %d to %d  [%d] \n", src, thisIndex, CkMyPe());
578 //#endif           
579     delete m;
580     mainProxy.next2();
581   }
582   
583
584   void receive3(eachToManyMessage* m) { 
585     int srcElt, srcPE, destPE, iter;
586     sscanf(m->msg,"%d %d %d",&srcElt, &srcPE, &iter);
587     delete m; 
588     mainProxy.next3(srcElt, srcPE, (int)thisIndex, CkMyPe());
589 #if DEBUG
590     if(iter==14){
591       CkPrintf("[%d] receive3 from srcElt=%d srcPE=%d iter=%d thisElt=%d\n", CkMyPe(), srcElt, srcPE, iter, thisIndex);
592       fflush(stdout);
593     }
594 #endif
595   } 
596   
597   
598   void receive4(eachToManyMessage* m) {
599     delete m;
600 //    CkPrintf("receive4\n");
601     mainProxy.next4();
602   }
603   
604   
605 };
606
607 #include "eachtomany.def.h"