strip out debug prints
[charm.git] / tests / charm++ / pingpong / pingpong.C
1 #include <string.h> // for strlen, and strcmp
2 #include <charm++.h>
3
4 #define NITER 10000
5 #define PAYLOAD 100
6 #ifdef CMK_USE_IBVERBS 
7 int iterations;
8 int payload;
9 extern "C" {
10   int CmiDirect_createHandle(int senderProc,void *recvBuf, int recvBufSize, void (*callbackFnPtr)(void *), void *callbackData);
11
12   void CmiDirect_assocLocalBuffer(int recverProc,int handle,void *sendBuf,int sendBufSize);
13   void CmiDirect_put(int recverProc,int handle);
14 }
15 #endif
16 class Fancy
17 {
18   char _str[12];
19   public:
20     Fancy() { _str[0] = '\0'; }
21     Fancy(char *str) {
22       strncpy(_str, str, 12);
23     }
24     int equals(char *str) { return !strcmp(str, _str); }
25 };
26
27 class CkArrayIndexFancy : public CkArrayIndex {
28   Fancy f;
29   public:
30     CkArrayIndexFancy(char *str) : f(str) {nInts=3;}
31 };
32
33 #include "pingpong.decl.h"
34
35 class PingMsg : public CMessage_PingMsg
36 {
37   public:
38     char *x;
39
40 };
41
42 class IdMsg : public CMessage_IdMsg
43 {
44   public:
45     CkChareID cid;
46     IdMsg(CkChareID _cid) : cid(_cid) {}
47 };
48
49 CProxy_main mainProxy;
50
51 #define P1 0
52 #define P2 1%CkNumPes()
53
54 class main : public Chare
55 {
56   int phase;
57   CProxy_Ping1 arr1;
58   CProxy_Ping2 arr2;
59   CProxy_Ping3 arr3;
60   CProxy_PingF arrF;
61   CProxy_PingC cid;
62   CProxy_PingG gid;
63   CProxy_PingN ngid;
64 public:
65   main(CkMigrateMessage *m) {}
66   main(CkArgMsg* m)
67   {
68     delete m;
69     if(CkNumPes()>2) {
70       CkAbort("Run this program on 1 or 2 processors only.\n");
71     }
72
73     iterations=NITER;
74     payload=PAYLOAD;
75     if(m->argc>1)
76       payload=atoi(m->argv[1]);
77     if(m->argc>2)
78       iterations=atoi(m->argv[2]);
79     if(m->argc>3)
80       CkPrintf("Usage: pgm +pN [payload] [iterations]\n Where N [1-2], payload (default %d) is integer >0 iterations (default %d) is integer >0 ", PAYLOAD, NITER);
81     CkPrintf("Pingpong with payload: %d iterations: %d\n", payload,iterations);
82     mainProxy = thishandle;
83     phase = 0;
84     gid = CProxy_PingG::ckNew();
85     ngid = CProxy_PingN::ckNew();
86     cid=CProxy_PingC::ckNew(1%CkNumPes());
87     cid=CProxy_PingC::ckNew(new IdMsg(cid.ckGetChareID()),0);
88     arr1 = CProxy_Ping1::ckNew(2);
89     arr2 = CProxy_Ping2::ckNew();
90     arr3 = CProxy_Ping3::ckNew();
91     arrF = CProxy_PingF::ckNew();
92     arr2(0,0).insert(P1);
93     arr2(0,1).insert(P2);
94     arr2.doneInserting();
95     arr3(0,0,0).insert(P1);
96     arr3(0,0,1).insert(P2);
97     arr3.doneInserting();
98     arrF[CkArrayIndexFancy("first")].insert(P1);
99     arrF[CkArrayIndexFancy("second")].insert(P2);
100     arrF.doneInserting();
101     phase=0;
102     mainProxy.maindone();
103   };
104
105   void maindone(void)
106   {
107     switch(phase++) {
108       case 0:
109         arr1[0].start();
110         break;
111       case 1:
112         arr2(0,0).start();
113         break;
114       case 2:
115         arr3(0,0,0).start();
116         break;
117       case 3:
118         arrF[CkArrayIndexFancy("first")].start();
119         break;
120       case 4:
121         cid.start();
122         break;
123       case 5:
124         gid[0].start();
125         break;
126 #ifndef CMK_USE_IBVERBS
127       case 6:
128         ngid[0].start();
129         break;
130 #else
131       case 6:
132         if(CkNumNodes()==2)
133           {
134             ngid[0].startRDMA();
135             break;
136           }
137         else
138           CkPrintf("RDMA skipped, you only have 1 node\n");
139         // drop through to next case
140 #endif
141       default:
142         CkExit();
143     }
144   };
145 };
146
147 class PingG : public Group
148 {
149   CProxyElement_PingG *pp;
150   int niter;
151   int me, nbr;
152   double start_time, end_time;
153 public:
154   PingG()
155   {
156     me = CkMyPe();    
157     nbr = (me+1)%CkNumPes();
158     pp = new CProxyElement_PingG(thisgroup,nbr);
159     niter = 0;
160   }
161   PingG(CkMigrateMessage *m) {}
162   void start(void)
163   {
164     start_time = CkWallTimer();
165     (*pp).recv(new (payload) PingMsg);
166   }
167   void recv(PingMsg *msg)
168   {
169     if(me==0) {
170       niter++;
171       if(niter==iterations) {
172         end_time = CkWallTimer();
173         int titer = (CkNumPes()==1)?(iterations/2) : iterations;
174         CkPrintf("Roundtrip time for Groups is %lf us\n",
175                  1.0e6*(end_time-start_time)/titer);
176         delete msg;
177         mainProxy.maindone();
178       } else {
179         (*pp).recv(msg);
180       }
181     } else {
182       (*pp).recv(msg);
183     }
184   }
185 };
186
187
188 class PingN : public NodeGroup
189 {
190   CProxyElement_PingN *pp;
191   int niter;
192   int me, nbr;
193 #ifdef CMK_USE_IBVERBS 
194   int rhandle;
195   int shandle;
196   char *rbuff;
197   char *sbuff;
198 #endif
199   double start_time, end_time;
200 public:
201   PingN()
202   {
203     me = CkMyNode();    
204     nbr = (me+1)%CkNumNodes();
205
206     // note: for RMDA in ping you can only have 1 nbr who is both your
207     // upstream and downstream which makes this an artificially simple
208     // calculation.
209
210     pp = new CProxyElement_PingN(thisgroup,nbr);
211     niter = 0;
212 #ifdef CMK_USE_IBVERBS 
213     rhandle=-1;
214     shandle=-1;
215     rbuff=(char *) malloc(payload*sizeof(char));
216     sbuff=(char *) malloc(payload*sizeof(char));
217     // setup persistent comm sender and receiver side
218     rhandle=CmiDirect_createHandle(nbr,rbuff,payload*sizeof(char),PingN::Wrapper_To_CallBack,(void *) this);
219     (*pp).recvHandle(rhandle);
220 #endif
221   }
222   PingN(CkMigrateMessage *m) {}
223   void recvHandle(int _shandle)
224   {
225 #ifdef CMK_USE_IBVERBS 
226     shandle=_shandle;
227     CmiDirect_assocLocalBuffer(nbr,shandle,sbuff,payload);
228 #endif
229   }
230   void start(void)
231   {
232     start_time = CkWallTimer();
233     (*pp).recv(new (payload) PingMsg);
234   }
235   void startRDMA(void)
236   {
237     niter=0;
238     start_time = CkWallTimer();
239 #ifdef CMK_USE_IBVERBS 
240     CkAssert(shandle>=0);
241     CmiDirect_put(nbr,shandle);
242 #else
243     CkAbort("do not call startRDMA if you don't actually have RDMA");
244 #endif
245   }
246
247   void recv(PingMsg *msg)
248   {
249     if(me==0) {
250       niter++;
251       if(niter==iterations) {
252         end_time = CkWallTimer();
253         int titer = (CkNumNodes()==1)?(iterations/2) : iterations;
254         CkPrintf("Roundtrip time for NodeGroups is %lf us\n",
255                  1.0e6*(end_time-start_time)/titer);
256         delete msg;
257         mainProxy.maindone();
258       } else {
259         (*pp).recv(msg);
260       }
261     } else {
262       (*pp).recv(msg);
263     }
264   }
265   static void Wrapper_To_CallBack(void* pt2Object){
266     // explicitly cast to a pointer to PingN
267     PingN* mySelf = (PingN*) pt2Object;
268
269     // call member
270     mySelf->recvRDMA();
271   }
272   // not an entry method, called via Wrapper_To_Callback
273   void recvRDMA()
274   {
275     if(me==0) {
276       niter++;
277       if(niter==iterations) {
278         end_time = CkWallTimer();
279         int titer = (CkNumNodes()==1)?(iterations/2) : iterations;
280         CkPrintf("Roundtrip time for NodeGroups RDMA is %lf us\n",
281                  1.0e6*(end_time-start_time)/titer);
282         mainProxy.maindone();
283       } else {
284 #ifdef CMK_USE_IBVERBS 
285         CmiDirect_put(nbr,shandle);
286 #else
287         CkAbort("do not call startRDMA if you don't actually have RDMA");
288 #endif
289       }
290     } else {
291 #ifdef CMK_USE_IBVERBS 
292       CmiDirect_put(nbr,shandle);
293 #else
294       CkAbort("do not call startRDMA if you don't actually have RDMA");
295 #endif
296     }
297   }
298
299 };
300
301
302 class Ping1 : public ArrayElement1D
303 {
304   CProxy_Ping1 *pp;
305   int niter;
306   double start_time, end_time;
307 public:
308   Ping1()
309   {
310     pp = new CProxy_Ping1(thisArrayID);
311     niter = 0;
312   }
313   Ping1(CkMigrateMessage *m) {}
314   void start(void)
315   {
316     (*pp)[1].recv(new (payload) PingMsg);
317     start_time = CkWallTimer();
318   }
319   void recv(PingMsg *msg)
320   {
321     if(thisIndex==0) {
322       niter++;
323       if(niter==iterations) {
324         end_time = CkWallTimer();
325         CkPrintf("Roundtrip time for 1D Arrays is %lf us\n",
326                  1.0e6*(end_time-start_time)/iterations);
327         //mainProxy.maindone();
328         niter=0;
329         start_time = CkWallTimer();
330         (*pp)[0].trecv(msg);
331       } else {
332         (*pp)[1].recv(msg);
333       }
334     } else {
335       (*pp)[0].recv(msg);
336     }
337   }
338   void trecv(PingMsg *msg)
339   {
340     if(thisIndex==0) {
341       niter++;
342       if(niter==iterations) {
343         end_time = CkWallTimer();
344         CkPrintf("Roundtrip time for 1D threaded Arrays is %lf us\n",
345                  1.0e6*(end_time-start_time)/iterations);
346         mainProxy.maindone();
347       } else {
348         (*pp)[1].trecv(msg);
349       }
350     } else {
351       (*pp)[0].trecv(msg);
352     }
353   }
354 };
355
356 class Ping2 : public ArrayElement2D
357 {
358   CProxy_Ping2 *pp;
359   int niter;
360   double start_time, end_time;
361 public:
362   Ping2()
363   {
364     pp = new CProxy_Ping2(thisArrayID);
365     niter = 0;
366   }
367   Ping2(CkMigrateMessage *m) {}
368   void start(void)
369   {
370     (*pp)(0,1).recv(new (payload) PingMsg);
371     start_time = CkWallTimer();
372   }
373   void recv(PingMsg *msg)
374   {
375     if(thisIndex.y==0) {
376       niter++;
377       if(niter==iterations) {
378         end_time = CkWallTimer();
379         CkPrintf("Roundtrip time for 2D Arrays is %lf us\n",
380                  1.0e6*(end_time-start_time)/iterations);
381         mainProxy.maindone();
382       } else {
383         (*pp)(0,1).recv(msg);
384       }
385     } else {
386       (*pp)(0,0).recv(msg);
387     }
388   }
389 };
390
391 class Ping3 : public ArrayElement3D
392 {
393   CProxy_Ping3 *pp;
394   int niter;
395   double start_time, end_time;
396 public:
397   Ping3()
398   {
399     pp = new CProxy_Ping3(thisArrayID);
400     niter = 0;
401   }
402   Ping3(CkMigrateMessage *m) {}
403   void start(void)
404   {
405     (*pp)(0,0,1).recv(new (payload) PingMsg);
406     start_time = CkWallTimer();
407   }
408   void recv(PingMsg *msg)
409   {
410     if(thisIndex.z==0) {
411       niter++;
412       if(niter==iterations) {
413         end_time = CkWallTimer();
414         CkPrintf("Roundtrip time for 3D Arrays is %lf us\n",
415                  1.0e6*(end_time-start_time)/iterations);
416         mainProxy.maindone();
417       } else {
418         (*pp)(0,0,1).recv(msg);
419       }
420     } else {
421       (*pp)(0,0,0).recv(msg);
422     }
423   }
424 };
425
426 class PingF : public CBase_PingF
427 {
428   CProxy_PingF *pp;
429   int niter;
430   double start_time, end_time;
431   int first;
432 public:
433   PingF()
434   {
435     pp = new CProxy_PingF(thisArrayID);
436     niter = 0;
437     first = thisIndex.equals("first") ? 1 : 0;
438   }
439   PingF(CkMigrateMessage *m) {}
440   void start(void)
441   {
442     (*pp)[CkArrayIndexFancy("second")].recv(new (payload) PingMsg);
443     start_time = CkWallTimer();
444   }
445   void recv(PingMsg *msg)
446   {
447     CkArrayIndexFancy partner((char *)(first?"second" : "first"));
448     if(first) {
449       niter++;
450       if(niter==iterations) {
451         end_time = CkWallTimer();
452         CkPrintf("Roundtrip time for Fancy Arrays is %lf us\n",
453                  1.0e6*(end_time-start_time)/iterations);
454         delete msg;
455         mainProxy.maindone();
456       } else {
457         (*pp)[partner].recv(msg);
458       }
459     } else {
460       (*pp)[partner].recv(msg);
461     }
462   }
463 };
464
465 class PingC : public Chare
466 {
467   CProxy_PingC *pp;
468   int niter;
469   double start_time, end_time;
470   int first;
471  public:
472   PingC(void)
473   {
474     first = 0;
475   }
476   PingC(IdMsg *msg)
477   {
478     first = 1;
479     CProxy_PingC pc(msg->cid);
480     msg->cid = thishandle;
481     pc.exchange(msg);
482   }
483   PingC(CkMigrateMessage *m) {}
484   void start(void)
485   {
486     niter = 0;
487     pp->recvReuse(new (payload) PingMsg);
488     start_time = CkWallTimer();
489   }
490   void exchange(IdMsg *msg)
491   {
492     if(first) {
493       pp = new CProxy_PingC(msg->cid);
494       delete msg;
495     } else {
496       pp = new CProxy_PingC(msg->cid);
497       msg->cid = thishandle;
498       pp->exchange(msg);
499     }
500   }
501   void recvReuse(PingMsg *msg)
502   {
503     if(first) {
504       niter++;
505       if(niter==iterations) {
506         end_time = CkWallTimer();
507         CkPrintf("Roundtrip time for Chares (reuse msgs) is %lf us\n",
508                  1.0e6*(end_time-start_time)/iterations);
509         niter = 0;
510         delete msg;
511         pp->recv(new (payload) PingMsg);
512         start_time = CkWallTimer();
513       } else {
514         pp->recvReuse(msg);
515       }
516     } else {
517       pp->recvReuse(msg);
518     }
519   }
520   void recv(PingMsg *msg)
521   {
522     delete msg;
523     if(first) {
524       niter++;
525       if(niter==iterations) {
526         end_time = CkWallTimer();
527         CkPrintf("Roundtrip time for Chares (new/del msgs) is %lf us\n",
528                  1.0e6*(end_time-start_time)/iterations);
529         niter = 0;
530         pp->trecv(new (payload) PingMsg);
531         start_time = CkWallTimer();
532       } else {
533         pp->recv(new (payload) PingMsg);
534       }
535     } else {
536       pp->recv(new (payload) PingMsg);
537     }
538   }
539   void trecv(PingMsg *msg)
540   {
541     if(first) {
542       niter++;
543       if(niter==iterations) {
544         end_time = CkWallTimer();
545         CkPrintf("Roundtrip time for threaded Chares (reuse) is %lf us\n",
546                  1.0e6*(end_time-start_time)/iterations);
547         delete msg;
548         mainProxy.maindone();
549       } else {
550         pp->trecv(msg);
551       }
552     } else {
553       pp->trecv(msg);
554     }
555   }
556 };
557 #include "pingpong.def.h"