Revert "Drop requirement for user code to call CBase_foo::pup(p)"
[charm.git] / tests / charm++ / commtest / comlib / benchmulti.C
1
2 /*******************************************
3         This benchmark tests all to all multicast in Charm++ using the
4         communication library.
5
6          To Run
7              benchmulti <message_size> <array_elements>
8
9          Defaults
10            message size = 128b
11            array elements = CkNumPes
12
13          Performance tips
14             - Use a maxpass of 1000
15             - Use +LBOff to remove loadbalancing overheads
16
17 Sameer Kumar 10/28/04      
18 **************************************************/
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #include <sys/time.h>
24 #include <sys/resource.h>
25 #include <unistd.h>
26
27 #include "ComlibManager.h"
28 #include "EachToManyMulticastStrategy.h"
29 #include "BroadcastStrategy.h"
30 #include "bench.decl.h"
31
32 #define USELIB
33 #define MAXPASS 10
34
35 int MESSAGESIZE=128;
36 /*readonly*/ CkChareID mid;
37 /*readonly*/ CProxy_Bench arr;
38 /*readonly*/ int nElements;
39
40 //Old stupid way of creating messages
41 class BenchMessage : public CMessage_BenchMessage {
42 public:
43     int size;
44     char *data;
45     int src;
46     
47     static void *alloc(int mnum, size_t size, int *sizes, int priobits){
48         int total_size = size + sizeof(char) * sizes[0];
49         BenchMessage *dmsg = (BenchMessage *)CkAllocMsg(mnum, total_size, 
50                                                         priobits);
51         dmsg->size = sizes[0];        
52         return (void *)dmsg;
53     }
54     
55     static void *pack(BenchMessage *msg){
56         return (void *)msg;
57     }
58     
59     static BenchMessage *unpack(void *buf){
60         BenchMessage *bmsg = (BenchMessage *)buf;
61         return bmsg;
62     }
63 };
64
65 /*mainchare*/
66 class Main : public CBase_Main
67 {
68     int pass, superpass;
69     double curTime;
70 public:
71     Main(CkArgMsg* m)
72     {
73         //Process command-line arguments
74         pass = 0;
75         superpass = 0;
76         nElements= CkNumPes();
77
78         if(m->argc > 1 ) MESSAGESIZE=atoi(m->argv[1]);
79
80         if(m->argc > 2 ) nElements=atoi(m->argv[2]);
81
82         delete m;
83         
84         CkPrintf("Running Bench on %d processors for %d elements with %d byte messages\n", CkNumPes(), nElements, MESSAGESIZE);
85         
86         mid = thishandle;        
87
88         arr = CProxy_Bench::ckNew();
89                 
90         int count = 0;
91         CkArrayIndex *elem_array = new CkArrayIndex[nElements];
92         for(count = 0; count < nElements; count ++) {
93             elem_array[count] = CkArrayIndex1D(count);
94         }
95
96         //Create strategy
97         EachToManyMulticastStrategy *strat = new 
98             EachToManyMulticastStrategy(USE_MESH, arr.ckGetArrayID(), 
99                                         arr.ckGetArrayID(),
100                                         nElements, elem_array,
101                                         nElements, elem_array);
102
103         //Use the multicast learner
104         strat->setMulticast();
105         strat->enableLearning();
106
107         //Alltoall multicast is effectively an all-to-all broadcast.
108         //So we can try the broadcast strategy here too
109         BroadcastStrategy *bstrat = new BroadcastStrategy
110             (arr.ckGetArrayID(), USE_HYPERCUBE);
111         
112         //CkPrintf("After creating array\n");
113         CkArrayID aid = arr.ckGetArrayID();
114
115         ComlibInstanceHandle cinst = CkGetComlibInstance();        
116         cinst.setStrategy(strat);
117         ComlibPrintf("After register strategy\n");
118
119         for(count = 0; count < nElements; count++)
120             arr[count].insert(cinst);
121         arr.doneInserting();
122         
123         curTime = CkWallTimer();
124         arr.sendMessage();
125         //        CkPrintf("After Main\n");
126     };
127     
128     void send(void) {
129         
130         static int count = 0;
131         count ++;
132
133         if (count == nElements){
134             pass ++;
135             count = 0;
136             arr.sendMessage();
137         }
138     }
139     
140     //Finished a phase, increase message size and start next phase
141     void done()
142     {
143         static int count = 0;
144         
145         count ++;
146         
147         if(count == nElements) {
148             CkPrintf("%d %5.4lf\n", MESSAGESIZE, (CmiWallTimer() - curTime)*1000/MAXPASS);
149
150             curTime = CkWallTimer();
151             superpass ++;
152             pass = 0;
153             count = 0;
154
155             if(superpass == 10)
156                 CkExit();
157             else {
158                 if(superpass < 20)
159                     MESSAGESIZE += 50;
160                 else if(superpass < 30)
161                     MESSAGESIZE += 100;
162                 else if(superpass < 40)
163                     MESSAGESIZE += 200;
164                 else if(superpass < 50)
165                     MESSAGESIZE += 500;
166                 
167                 arr.start(MESSAGESIZE);
168             }
169         }
170     }
171 };
172
173
174 //Charm++ array to do all-to-all multicast
175 /*array [1D]*/
176 class Bench : public CBase_Bench 
177 {
178     int pass;
179     int mcount;
180     double time, startTime;
181     int firstEntryFlag, sendFinishedFlag;
182     CProxy_Bench arrd;
183     ComlibInstanceHandle myinst;
184
185 public:
186
187     //A pup to migrate elements, because we always need one 
188     void pup(PUP::er &p) {
189         //if(p.isPacking())
190         //  CkPrintf("Migrating from %d\n", CkMyPe());
191
192         CBase_Bench::pup(p);
193         p | pass ;
194         p | mcount ;
195         p | time;
196         p | startTime;
197         p | firstEntryFlag ;
198         p | sendFinishedFlag ;
199         p | myinst;
200         p | arrd;
201     }
202   
203     //Constructor
204     Bench(ComlibInstanceHandle cinst)
205     {   
206         pass = 0;
207         mcount = 0;
208         time = 0.0;
209         
210         firstEntryFlag = 0;
211         sendFinishedFlag = 0;
212
213         arrd = thisProxy;
214         ComlibDelegateProxy(&arrd);
215
216         CkArrayIndex *elem_array = new CkArrayIndex[nElements];
217         for(int count = 0; count < nElements; count ++) 
218             elem_array[count] = CkArrayIndex1D(count);
219         
220         usesAtSync = CmiTrue;
221         setMigratable(true);
222         myinst = cinst;
223     }
224     
225     //Migrate constrctor
226     Bench(CkMigrateMessage *m) {
227         //        CkPrintf(" Migrated to %d\n", CkMyPe());
228     }
229     
230     //Send the multicast message, notice only one is sent.
231     void sendMessage()
232     {
233         if(thisIndex >= nElements) {
234             finishPass();
235             return;
236         }
237         
238 #ifdef USELIB
239         myinst.beginIteration();
240 #endif
241
242         int count = 0;
243         int size = MESSAGESIZE;
244         
245 #ifdef USELIB
246         arrd.receiveMessage(new(&size, 0) BenchMessage);
247 #else
248         arr[count].receiveMessage(new (&size, 0) BenchMessage);
249 #endif
250
251 #ifdef USELIB
252         myinst.endIteration();
253 #endif
254
255         sendFinishedFlag = 1;   
256     }
257
258     //Receive messages. Once all are received, initiate next step with
259     //larger message size
260     void receiveMessage(BenchMessage *bmsg){
261         
262         ComlibPrintf("[%d][%d] In Receive Message \n", CkMyPe(), thisIndex);
263         
264         if(!firstEntryFlag) {
265             startTime = CkWallTimer();
266             firstEntryFlag = 1;
267         }
268         
269         delete bmsg;
270         
271         mcount ++;
272
273         if(mcount == nElements){
274             finishPass();
275         }
276     }
277
278     void start(int messagesize){
279         //CkPrintf("In Start\n");
280         MESSAGESIZE = messagesize;
281         
282         if(firstEntryFlag) {
283             //            CkPrintf("Calling AtSync\n");
284             AtSync();
285         }
286         else
287             sendMessage();
288     }
289
290     //Resume from loadbalancing
291     void ResumeFromSync() {
292         myinst.setSourcePe();
293         sendMessage();
294     }
295
296     void finishPass(){
297         mcount = 0;            
298         pass ++;        
299         time += CkWallTimer() - startTime;
300
301         CProxy_Main mainProxy(mid);
302         if(pass == MAXPASS){
303             pass = 0;
304             mainProxy.done();
305         }
306         else {
307             sendMessage();
308             int x = 0;
309         }
310         
311         sendFinishedFlag = 0;
312     }
313 };
314
315 #include "bench.def.h"