fc5e4c44384c3f2833d77de59226709d856832df
[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 Chare
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         CkArrayIndexMax *elem_array = new CkArrayIndexMax[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
106         //Alltoall multicast is effectively an all-to-all broadcast.
107         //So we can try the broadcast strategy here too
108         BroadcastStrategy *bstrat = new BroadcastStrategy
109             (arr.ckGetArrayID(), USE_HYPERCUBE);
110         
111         //CkPrintf("After creating array\n");
112         CkArrayID aid = arr.ckGetArrayID();
113
114         ComlibInstanceHandle cinst = CkGetComlibInstance();        
115         cinst.setStrategy(strat);
116         ComlibPrintf("After register strategy\n");
117
118         for(count = 0; count < nElements; count++)
119             arr[count].insert(cinst);
120         arr.doneInserting();
121         
122         curTime = CkWallTimer();
123         arr.sendMessage();
124         //        CkPrintf("After Main\n");
125     };
126     
127     void send(void) {
128         
129         static int count = 0;
130         count ++;
131
132         if (count == nElements){
133             pass ++;
134             count = 0;
135             arr.sendMessage();
136         }
137     }
138     
139     //Finished a phase, increase message size and start next phase
140     void done()
141     {
142         static int count = 0;
143         
144         count ++;
145         
146         if(count == nElements) {
147             CkPrintf("%d %5.4lf\n", MESSAGESIZE, (CmiWallTimer() - curTime)*1000/MAXPASS);
148
149             curTime = CkWallTimer();
150             superpass ++;
151             pass = 0;
152             count = 0;
153
154             if(superpass == 10)
155                 CkExit();
156             else {
157                 if(superpass < 20)
158                     MESSAGESIZE += 50;
159                 else if(superpass < 30)
160                     MESSAGESIZE += 100;
161                 else if(superpass < 40)
162                     MESSAGESIZE += 200;
163                 else if(superpass < 50)
164                     MESSAGESIZE += 500;
165                 
166                 arr.start(MESSAGESIZE);
167             }
168         }
169     }
170 };
171
172
173 //Charm++ array to do all-to-all multicast
174 /*array [1D]*/
175 class Bench : public CBase_Bench 
176 {
177     int pass;
178     int mcount;
179     double time, startTime;
180     int firstEntryFlag, sendFinishedFlag;
181     CProxy_Bench arrd;
182     ComlibInstanceHandle myinst;
183
184 public:
185
186     //A pup to migrate elements, because we always need one 
187     void pup(PUP::er &p) {
188         //if(p.isPacking())
189         //  CkPrintf("Migrating from %d\n", CkMyPe());
190
191         ArrayElement1D::pup(p);
192         p | pass ;
193         p | mcount ;
194         p | time;
195         p | startTime;
196         p | firstEntryFlag ;
197         p | sendFinishedFlag ;
198         p | myinst;
199         p | arrd;
200     }
201   
202     //Constructor
203     Bench(ComlibInstanceHandle cinst)
204     {   
205         pass = 0;
206         mcount = 0;
207         time = 0.0;
208         
209         firstEntryFlag = 0;
210         sendFinishedFlag = 0;
211
212         arrd = thisProxy;
213         ComlibDelegateProxy(&arrd);
214
215         CkArrayIndexMax *elem_array = new CkArrayIndexMax[nElements];
216         for(int count = 0; count < nElements; count ++) 
217             elem_array[count] = CkArrayIndex1D(count);
218         
219         usesAtSync = CmiTrue;
220         setMigratable(true);
221         myinst = cinst;
222     }
223     
224     //Migrate constrctor
225     Bench(CkMigrateMessage *m) {
226         //        CkPrintf(" Migrated to %d\n", CkMyPe());
227     }
228     
229     //Send the multicast message, notice only one is sent.
230     void sendMessage()
231     {
232         if(thisIndex >= nElements) {
233             finishPass();
234             return;
235         }
236         
237 #ifdef USELIB
238         myinst.beginIteration();
239 #endif
240
241         int count = 0;
242         int size = MESSAGESIZE;
243         
244 #ifdef USELIB
245         arrd.receiveMessage(new(&size, 0) BenchMessage);
246 #else
247         arr[count].receiveMessage(new (&size, 0) BenchMessage);
248 #endif
249
250 #ifdef USELIB
251         myinst.endIteration();
252 #endif
253
254         sendFinishedFlag = 1;   
255     }
256
257     //Receive messages. Once all are received, initiate next step with
258     //larger message size
259     void receiveMessage(BenchMessage *bmsg){
260         
261         ComlibPrintf("[%d][%d] In Receive Message \n", CkMyPe(), thisIndex);
262         
263         if(!firstEntryFlag) {
264             startTime = CkWallTimer();
265             firstEntryFlag = 1;
266         }
267         
268         delete bmsg;
269         
270         mcount ++;
271
272         if(mcount == nElements){
273             finishPass();
274         }
275     }
276
277     void start(int messagesize){
278         //CkPrintf("In Start\n");
279         MESSAGESIZE = messagesize;
280         
281         if(firstEntryFlag) {
282             //            CkPrintf("Calling AtSync\n");
283             AtSync();
284         }
285         else
286             sendMessage();
287     }
288
289     //Resume from loadbalancing
290     void ResumeFromSync() {
291         myinst.setSourcePe();
292         sendMessage();
293     }
294
295     void finishPass(){
296         mcount = 0;            
297         pass ++;        
298         time += CkWallTimer() - startTime;
299
300         CProxy_Main mainProxy(mid);
301         if(pass == MAXPASS){
302             pass = 0;
303             mainProxy.done();
304         }
305         else {
306             sendMessage();
307             int x = 0;
308         }
309         
310         sendFinishedFlag = 0;
311     }
312 };
313
314 #include "bench.def.h"