Revert "Drop requirement for user code to call CBase_foo::pup(p)"
[charm.git] / tests / charm++ / commtest / comlib / hello.C
1 /**
2 Tiny test program that
3   1.) Creates a simple 1D array
4   2.) Asks the array to do a multicast operation--
5       each element is told what to send, and 
6       what it should expect to receive.
7   3.) Synchronize, and go back to 2.
8
9 If SKIP_COMLIB is not set, uses the comlib
10 for the multicast operation.
11
12 Orion Sky Lawlor, olawlor@acm.org, 2003/7/15
13 Migration test in commlib added on 2004/05/12, Sameer Kumar
14 */
15
16 #include <stdio.h>
17 #include "EachToManyMulticastStrategy.h" /* for ComlibManager Strategy*/
18
19 #include "hello.decl.h"
20
21 /*readonly*/ CProxy_Main mainProxy;
22 /*readonly*/ int nElements;
23
24 /*mainchare*/
25 class Main : public CBase_Main
26 {
27   int **commMatrix; /* commMatrix[s][r]= # messages sent from s to r */
28   int *commSend, *commRecv; /* temporary storage for "send" */
29   CProxy_Hello arr;
30   int nIter; // Iterations remaining
31 public:
32   Main(CkArgMsg* m)
33   {
34     //Process command-line arguments
35     nElements=5;
36     int strat=USE_MESH;
37     if(m->argc>1) nElements=atoi(m->argv[1]);
38     if (m->argc>2) strat=atoi(m->argv[2]); /* FIXME: use "+strategy" flag */
39     delete m;
40     
41     // For the first step, use an all-to-all communication pattern.
42     commMatrix=new int*[nElements];
43     for (int i=0;i<nElements;i++) {
44       commMatrix[i]=new int[nElements];
45       for (int j=0;j<nElements;j++)
46         commMatrix[i][j]=1;
47     }
48     commSend=new int[nElements]; 
49     commRecv=new int[nElements];
50
51     //Start the computation
52     CkPrintf("Running Hello on %d processors for %d elements: strategy %d\n",
53              CkNumPes(),nElements, strat);
54     mainProxy = thishandle;
55     
56     ComlibInstanceHandle cinst=CkGetComlibInstance();
57
58     arr = CProxy_Hello::ckNew();
59    
60     EachToManyMulticastStrategy *strategy = new EachToManyMulticastStrategy
61         (strat, arr,arr);
62     cinst.setStrategy(strategy);
63     
64     CProxy_Hello hproxy(arr);
65     for(int count = 0; count < nElements; count++)
66         hproxy[count].insert(cinst);
67
68     hproxy.doneInserting();
69
70     nIter=0;
71     send();
72   };
73   
74   // Tell each element what to send and receive:
75   void send(void) {
76     CkPrintf("-------- starting iteration %d ---------\n",nIter);
77     for (int me=0;me<nElements;me++) {
78       for (int you=0;you<nElements;you++) {
79           commSend[you]=commMatrix[me][you]; //Stuff I send to you
80           commRecv[you]=commMatrix[you][me]; //Stuff you send to me
81       }
82       arr[me].startMcast(nIter,commSend,commRecv);
83     }
84   }
85
86   // This multicast iteration is complete.
87   void done(void)
88   {
89     CkPrintf("-------- finished iteration %d ---------\n",nIter);
90     nIter++;
91     if (nIter == 10) {
92       CkPrintf("All done\n");
93       CkExit();
94     }
95     else {
96       reset();
97       send();
98     }
99   }
100   
101   // Reset the send/recv matrix to random values
102   void reset(void) {
103     for (int i=0;i<nElements;i++)
104       for (int j=0;j<nElements;j++)
105           commMatrix[i][j]=(rand()%3);
106   }
107 };
108
109 /*array [1D]*/
110 class Hello : public CBase_Hello 
111 {
112   int curIter; // Current iteration number (only one can be running at a time)
113   int *willRecv; // counts # of message we will recv, per source
114   int *haveRecv; // counts # of messages we have recv'd, per source
115   bool verbose; // generate debugging output for every start/send/recv/end.
116   ComlibInstanceHandle comlib;
117   CProxy_Hello hProxy; // delegated comlib proxy.
118   
119   void reset(void) {
120     int i;
121     for (i=0;i<nElements;i++) haveRecv[i]=0; // Haven't got any yet
122     for (i=0;i<nElements;i++) willRecv[i]=-1; // Don't know how many we will get
123   }
124   // Call endMcast if we have received everything for this iteration.
125   void tryEnd(void) {
126     for (int i=0;i<nElements;i++) 
127       if (willRecv[i]!=haveRecv[i])
128         return;
129     endMcast();
130   }
131   // Verify that we don't have too many messages from "src".
132   void checkOver(int src) {
133     if (willRecv[src]!=-1 && haveRecv[src]>willRecv[src]) {
134       CkError("Element %d received too many messages from %d (expected %d, got %d)\n",
135         thisIndex, src, willRecv[src], haveRecv[src]);
136       CkAbort("Too many multicast messages!\n");
137     }
138   }
139 public:
140   Hello(ComlibInstanceHandle comlib_)       
141   {
142     comlib = comlib_;
143
144     verbose=false; // true;
145     if (verbose) CkPrintf("Element %d created\n",thisIndex);
146     willRecv=new int[nElements];
147     haveRecv=new int[nElements];
148     reset();
149     curIter=0;
150     hProxy=thisProxy;
151 #ifndef SKIP_COMLIB
152     ComlibDelegateProxy(&hProxy);
153 #endif
154   }
155
156   Hello(CkMigrateMessage *m) { 
157   }
158   
159   // Send out the number of messages listed in "send" for each element.
160   //  You'll receive from each element the number of messages listed in "recv".
161   // This routine is called by main, which knows both senders and receivers.
162   void startMcast(int nIter,const int *send,const int *recv)
163   {
164     if (curIter!=nIter) {
165       CkError("Element %d asked to start iter %d, but we're at %d\n",
166            thisIndex, nIter,curIter);
167       CkAbort("Unexpected iteration start message!\n");
168     }
169     
170     if(verbose) CkPrintf("[%d] Element %d iteration %d starting\n",CkMyPe(), thisIndex,curIter);
171     
172     comlib.beginIteration();
173     for (int dest=0;dest<nElements;dest++) {
174       for (int m=0;m<send[dest];m++) {
175           if(verbose) CkPrintf("Element %d iteration %d send to %d\n",thisIndex,curIter,dest);
176           hProxy[dest].midMcast(curIter,thisIndex);
177       }
178     }
179     comlib.endIteration();
180     
181     for (int src=0;src<nElements;src++) {
182         willRecv[src]=recv[src]; 
183         checkOver(src);
184     }
185     tryEnd();
186   }
187   
188   // Receive a multicast from this array element.
189   void midMcast(int nIter,int src) {
190     if (curIter!=nIter) {
191       CkError("Element %d received unexpected message from %d for iter %d (we're at %d)\n",
192            thisIndex,src, nIter,curIter);
193       CkAbort("Unexpected mcast message!\n");
194     }
195     if (verbose) CkPrintf("Element %d iteration %d recv from %d\n",thisIndex,curIter,src);
196     haveRecv[src]++; checkOver(src);
197     tryEnd();
198   }
199   
200   // This is the end of one multicast iteration.
201   //  Update state and contribute to mainchare reduction.
202   void endMcast(void) {
203     if (verbose) CkPrintf("Element %d iteration %d done\n",thisIndex,curIter);
204     curIter++;
205     reset();
206     contribute(0,0,CkReduction::sum_int,CkCallback(
207         CkIndex_Main::done(),mainProxy));
208
209     srandom((CkMyPe()+1) * thisIndex);
210     int dest_proc = random() % CkNumPes();
211
212     if(curIter > 4) {
213         //if (verbose) 
214         if(verbose) CkPrintf("[%d] Migrating to %d\n", CkMyPe(), dest_proc);
215         migrateMe(dest_proc);
216     }
217   }
218
219   void pup(PUP::er &p) {
220       CBase_Hello::pup(p);
221       p | comlib;
222       p | verbose;
223
224       p | hProxy;
225       p | curIter;
226       p | verbose;        
227
228       if(p.isUnpacking()) {
229           willRecv = new int[nElements];
230           haveRecv = new int[nElements];
231       }
232       
233       p(willRecv, nElements);
234       p(haveRecv, nElements);        
235   }
236 };
237
238 #include "hello.def.h"