Revert "Drop requirement for user code to call CBase_foo::pup(p)"
[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           CBase_EachToManyArray::pup(p);
457           p | cinst;
458           if(p.isUnpacking()){
459                   myDelegatedProxy = thisProxy;
460                   ComlibAssociateProxy(cinst, myDelegatedProxy);
461           }
462   }
463
464   
465   EachToManyArray(CkMigrateMessage *m) {
466 #if DEBUG
467           CkPrintf("Object %d has migrated to %d\n", thisIndex, CkMyPe());
468           fflush(stdout);
469 #endif
470   }
471   
472   void setup(ComlibInstanceHandle inst){
473           // We cannot put this in the constructor because the strategy may not yet have been created. Our references to it would therefore be invald.
474           cinst = inst;
475           myDelegatedProxy = thisProxy;
476           ComlibAssociateProxy(cinst, myDelegatedProxy); 
477           mainProxy.arraySetupDone();
478   }
479   
480   
481   void migrateMeTo(int toPe){
482           migrateMe (toPe);
483   }
484   
485     
486   void test1(int iter) {
487 #if DEBUG
488     CkPrintf("[%d] test1 iter=%d thisIndex=%d\n", CkMyPe(), iter, thisIndex);
489     fflush(stdout);
490 #endif
491     
492     // Build a message
493     char *msg = (char*)malloc(256);
494     sprintf(msg, "%d %d %d", thisIndex, CkMyPe(), iter); 
495     eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage;
496     memcpy(b->msg, msg, strlen(msg)+1);
497     b->length = strlen(msg);
498     // Broadcast the message to the whole array
499     ComlibBegin(myDelegatedProxy, iter);
500     myDelegatedProxy.receive1(b);
501     ComlibEnd(myDelegatedProxy, iter);
502     // Free the message
503     free(msg);
504   }
505
506    
507   void test2(int iter) {
508           // Build a message
509           char *msg = (char*)malloc(256);
510           sprintf(msg, "%d", thisIndex);
511           eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage;
512           memcpy(b->msg, msg, strlen(msg)+1);
513           b->length = strlen(msg);
514           // Broadcast the message to the whole array
515           ComlibBegin(myDelegatedProxy, iter);
516           myDelegatedProxy.receive2(b);
517           ComlibEnd(myDelegatedProxy, iter);
518           // Free the message
519           free(msg);
520   }
521
522
523   void test3(int iter) { 
524 #if DEBUG
525     CkPrintf("[%d] test3 iter=%d thisIndex=%d\n", CkMyPe(), iter, thisIndex);
526     fflush(stdout);
527 #endif
528
529           // Build a message 
530           char *msg = (char*)malloc(256); 
531           sprintf(msg, "%d %d %d", thisIndex, CkMyPe(), iter); 
532           eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage; 
533           memcpy(b->msg, msg, strlen(msg)+1); 
534           b->length = strlen(msg); 
535           // Broadcast the message to the whole array 
536           ComlibBegin(myDelegatedProxy, iter); 
537           myDelegatedProxy.receive3(b); 
538           ComlibEnd(myDelegatedProxy, iter); 
539           // Free the message 
540           free(msg); 
541   } 
542  
543   void test4(int iter) {
544           // Build a message
545           char *msg = (char*)malloc(256);
546           sprintf(msg, "%d", thisIndex);
547           eachToManyMessage* b = new(strlen(msg)+1,0) eachToManyMessage;
548           memcpy(b->msg, msg, strlen(msg)+1);
549           b->length = strlen(msg);
550           // Broadcast the message to the whole array
551           ComlibBegin(myDelegatedProxy, iter);
552           myDelegatedProxy.receive4(b);
553           ComlibEnd(myDelegatedProxy, iter);
554           // Free the message
555           free(msg);
556    }
557
558
559   
560   void receive1(eachToManyMessage* m) {      
561     int srcElt, srcPE, destPE, iter;
562     sscanf(m->msg,"%d %d %d",&srcElt, &srcPE, &iter);
563     delete m; 
564 #if DEBUG
565     CkPrintf("[%d] receive1 from srcElt=%d srcPE=%d iter=%d thisElt=%d\n", CkMyPe(), srcElt, srcPE, iter, thisIndex);
566     fflush(stdout);
567 #endif
568     mainProxy.next1();
569   }
570   
571   
572
573   void receive2(eachToManyMessage* m) {
574 //#if DEBUG
575 //  //    CkPrintf("[%d] Application: received message %s\n", CkMyPe(), m->msg);
576 //    int src;
577 //    sscanf(m->msg,"%d",&src);
578 //    CkPrintf("Test 2 Received: %d to %d  [%d] \n", src, thisIndex, CkMyPe());
579 //#endif           
580     delete m;
581     mainProxy.next2();
582   }
583   
584
585   void receive3(eachToManyMessage* m) { 
586     int srcElt, srcPE, destPE, iter;
587     sscanf(m->msg,"%d %d %d",&srcElt, &srcPE, &iter);
588     delete m; 
589     mainProxy.next3(srcElt, srcPE, (int)thisIndex, CkMyPe());
590 #if DEBUG
591     if(iter==14){
592       CkPrintf("[%d] receive3 from srcElt=%d srcPE=%d iter=%d thisElt=%d\n", CkMyPe(), srcElt, srcPE, iter, thisIndex);
593       fflush(stdout);
594     }
595 #endif
596   } 
597   
598   
599   void receive4(eachToManyMessage* m) {
600     delete m;
601 //    CkPrintf("receive4\n");
602     mainProxy.next4();
603   }
604   
605   
606 };
607
608 #include "eachtomany.def.h"