e65530caab650d1e9df7eeb895da93bed1463591
[charm.git] / tests / charm++ / commtest / comlib / bench.C
1
2 /***********************
3         This benchmark tests all to all personalized communication
4    in Charm++ using the communication library.
5
6          To Run
7              bench <message_size> <array_elements>
8
9          Defaults
10            message size = 128b
11            array elements = CkNumPes
12
13          Performance tips
14             - Use a maxiter 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 "charm++.h"
28 #include "ComlibManager.h"
29 #include "EachToManyMulticastStrategy.h"
30 #include "StreamingStrategy.h"
31 #include "DummyStrategy.h"
32 #include "bench.decl.h"
33
34 #define USELIB  1           // Use comlib or default charm++
35 #define MAXITER 10          // Number of iterations to run For
36                             // benchmark runs this should be atleast a
37                             // 1000
38
39 #define NUMPASS 1           // Number of all-to-all phases with the
40                             // same message size. After NUMPASS phases
41                             // the message size will be
42                             // increased. Useful while using the
43                             // learning framework.
44
45 /*readonly*/ CkChareID mid;
46 /*readonly*/ CProxy_Bench arr;
47 /*readonly*/ int nElements;
48
49 //Old way of creating messages in Charm++
50 class BenchMessage : public CMessage_BenchMessage {
51 public:
52     char *data;
53
54     static void *alloc(int mnum, size_t size, int *sizes, int priobits){
55         int total_size = size + CK_ALIGN(sizeof(char) * sizes[0], 8);
56         BenchMessage *dmsg = (BenchMessage *)CkAllocMsg(mnum, total_size, 
57                                                         priobits);
58         dmsg->data = (char *)dmsg + sizeof(BenchMessage);
59         return (void *)dmsg;    
60     }
61     
62     static void *pack(BenchMessage *msg){
63         return (void *)msg;
64     }
65     
66     static BenchMessage *unpack(void *buf){
67         BenchMessage *bmsg = (BenchMessage *)buf;
68         bmsg->data = (char *)bmsg + sizeof(BenchMessage);
69         return bmsg;
70     }
71 };
72
73 /*mainchare*/
74 class Main : public Chare
75 {
76     int pass, superpass;
77     double curTime;
78     int mcount;
79     int size;
80
81 public:
82     Main(CkArgMsg* m)
83     {
84         int stratID = 0;
85         //Process command-line arguments
86         pass = 0;
87         superpass = 0;
88         nElements = CkNumPes();
89
90         mcount = 0;
91
92         size = 128;
93         if(m->argc > 1 ) size = atoi(m->argv[1]);
94         if(m->argc > 2 ) 
95             nElements = atoi(m->argv[2]);
96         delete m;
97         
98         //Start the computation
99         CkPrintf("Running Bench on %d processors for %d elements with %d byte messages\n", CkNumPes(), nElements, size);
100         
101         mid = thishandle;        
102         //ComlibInstanceHandle tmpInstance = CkGetComlibInstance();
103         ComlibInstanceHandle cinst = CkGetComlibInstance();
104         
105         arr = CProxy_Bench::ckNew();
106         
107         int count = 0;
108         CkArrayIndexMax *elem_array = new CkArrayIndexMax[nElements];
109         for(count = 0; count < nElements; count ++) {
110             elem_array[count] = CkArrayIndex1D(count);
111         }
112
113         //Create strategy
114         EachToManyMulticastStrategy *strat = new 
115             EachToManyMulticastStrategy(USE_MESH, arr.ckGetArrayID(), 
116                                         arr.ckGetArrayID(), 
117                                         nElements, elem_array, 
118                                         nElements, elem_array);
119         
120         cinst.setStrategy(strat);                
121
122         for(count =0; count < nElements; count++)
123           arr[count].insert(cinst);
124
125         arr.doneInserting();
126
127         curTime = CkWallTimer();
128
129         //for(count = 0; count < nElements; count++)            
130         //  arr[count].start(size);
131
132         arr.start(size);
133     };
134     
135     void send(void) {
136         
137       mcount ++;
138       
139       if (mcount == nElements){
140         
141         pass ++;
142         mcount = 0;
143         
144         CkPrintf("%d %5.4lf\n", size, (CmiWallTimer() - curTime)*1000/
145                  MAXITER);
146         curTime = CkWallTimer();
147         
148         if(pass == NUMPASS)
149           done();
150         else {
151             //for(int count = 0; count < nElements; count++)            
152             //  arr[count].start(size);
153             arr.start(size);
154         }
155       }
156     }
157     
158     void done()
159     {   
160       superpass ++;
161       mcount = 0;
162       pass = 0;
163       
164       if(superpass == 10)
165           CkExit();
166       else {
167           if(superpass < 20)
168               size += 50;
169           else if(superpass < 30)
170               size += 100;
171           else if(superpass < 40)
172               size += 200;
173           else if(superpass < 50)
174               size += 500;
175           
176           //for(int count = 0; count < nElements; count++)            
177           //  arr[count].start(size);
178           arr.start(size);
179       }
180     }
181 };
182
183 /******** The all to all benchmar array *************/
184 /*array [1D]*/
185 class Bench : public ArrayElement1D
186 {
187     int pass;
188     int mcount;
189     int ite;
190     int msize;
191     double startTime;
192     ComlibInstanceHandle myInst;
193     CProxy_Bench arrd;      
194
195 public:
196   
197     Bench(ComlibInstanceHandle cinst)
198     {   
199         pass = 0;
200         mcount = 0;
201         ite = 0;
202         msize = 0;
203
204         myInst = cinst;
205
206         myInst.setSourcePe();
207
208         usesAtSync = CmiTrue;
209         setMigratable(true);
210
211         arrd = arr;
212         ComlibDelegateProxy(&arrd);
213     }
214     
215     Bench(CkMigrateMessage *m) {
216         //CkPrintf("Migrated to %d\n", CkMyPe());
217         //myInst = cinst;
218     }
219     
220     //Send all to all messages
221     //proxy arr is the charm++ proxy
222     //proxy arrd is the comlib delegated proxy
223     void sendMessage()
224     {
225 #ifdef USELIB
226         myInst.beginIteration();
227 #endif        
228         for(int count = 0; count < nElements; count ++){
229             
230             ComlibPrintf("[%d] Sending Message from %d to %d\n", CkMyPe(), thisIndex, count);
231
232 #ifdef USELIB
233             arrd[count].receiveMessage(new (&msize, 0) BenchMessage); 
234 #else
235             arr[count].receiveMessage(new (&msize, 0) BenchMessage);
236 #endif
237         }
238
239 #ifdef USELIB
240         myInst.endIteration();
241 #endif        
242     }
243
244     //receive the all to all messages Once I have everyones message I
245     //initiate the next iteration, or call loadbalancing.
246     void receiveMessage(BenchMessage *bmsg){
247         
248         delete bmsg;
249         mcount ++;
250         
251         ComlibPrintf("In Receive Message %d %d %d\n", thisIndex, CkMyPe(), 
252                      pass);
253
254         if(mcount == nElements){
255             mcount = 0;            
256             pass ++;            
257             CProxy_Main mainProxy(mid);
258
259             //If I have finished all iterations for this message size,
260             //Go back to main and start with a larger message size.
261             if(pass == MAXITER){
262                 pass = 0;                
263                 mainProxy.send();
264             }
265             else
266                 sendMessage();
267         }
268     }
269     
270     void start(int messagesize){
271         msize = messagesize;
272
273         //Initiate loadbalance at the phases 1 and NUMPASS/2
274         //So if NUMPASS = 1, loadbalancing will not be called 
275         if(ite % NUMPASS == NUMPASS/2 || ite % NUMPASS == 1) {
276             //Call atsync in the middle and in the end
277             ComlibPrintf("[%d] Calling Atsync\n", CkMyPe());
278             AtSync();
279         }
280         else
281             sendMessage();
282         
283         //CkPrintf("In Start\n");
284         ite ++;
285     }
286
287     //Finished loadbalancing
288     void ResumeFromSync() {
289         //        CkPrintf("%d: resuming\n", CkMyPe());
290         myInst.setSourcePe();
291         sendMessage();
292     }
293
294     //Pack the data for migration
295     void pup(PUP::er &p) {
296         //if(p.isPacking())
297         //  CkPrintf("Migrating from %d\n", CkMyPe());
298
299         ArrayElement1D::pup(p);
300         p | pass ;
301         p | mcount ;
302         p | ite ;
303         p | startTime;
304         p | arrd;
305         p | myInst;
306         p | msize;
307     }
308 };
309
310
311 #include "bench.def.h"
312