795b78512fb085dbd2ba98b2a6f45158433453cc
[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         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         CkArrayIndex *elem_array = new CkArrayIndex[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"