Initial checkin of move from pgms
[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
6 class Fancy
7 {
8   char _str[12];
9   public:
10     Fancy() { _str[0] = '\0'; }
11     Fancy(char *str) {
12       strncpy(_str, str, 12);
13     }
14     int equals(char *str) { return !strcmp(str, _str); }
15 };
16
17 class CkArrayIndexFancy : public CkArrayIndex {
18   Fancy f;
19   public:
20     CkArrayIndexFancy(char *str) : f(str) {nInts=3;}
21 };
22
23 #include "pingpong.decl.h"
24
25 class PingMsg : public CMessage_PingMsg
26 {
27   public:
28     char x[100];
29 };
30
31 class IdMsg : public CMessage_IdMsg
32 {
33   public:
34     CkChareID cid;
35     IdMsg(CkChareID _cid) : cid(_cid) {}
36 };
37
38 CProxy_main mainProxy;
39
40 #define P1 0
41 #define P2 1%CkNumPes()
42
43 class main : public Chare
44 {
45   int phase;
46   CProxy_Ping1 arr1;
47   CProxy_Ping2 arr2;
48   CProxy_Ping3 arr3;
49   CProxy_PingF arrF;
50   CProxy_PingC cid;
51   CProxy_PingG gid;
52 public:
53   main(CkMigrateMessage *m) {}
54   main(CkArgMsg* m)
55   {
56     delete m;
57     if(CkNumPes()>2) {
58       CkAbort("Run this program on 1 or 2 processors only.\n");
59     }
60     mainProxy = thishandle;
61     phase = 0;
62     gid = CProxy_PingG::ckNew();
63     cid=CProxy_PingC::ckNew(1%CkNumPes());
64     cid=CProxy_PingC::ckNew(new IdMsg(cid.ckGetChareID()),0);
65     arr1 = CProxy_Ping1::ckNew(2);
66     arr2 = CProxy_Ping2::ckNew();
67     arr3 = CProxy_Ping3::ckNew();
68     arrF = CProxy_PingF::ckNew();
69     arr2(0,0).insert(P1);
70     arr2(0,1).insert(P2);
71     arr2.doneInserting();
72     arr3(0,0,0).insert(P1);
73     arr3(0,0,1).insert(P2);
74     arr3.doneInserting();
75     arrF[CkArrayIndexFancy("first")].insert(P1);
76     arrF[CkArrayIndexFancy("second")].insert(P2);
77     arrF.doneInserting();
78     phase=0;
79     mainProxy.maindone();
80   };
81
82   void maindone(void)
83   {
84     switch(phase++) {
85       case 0:
86         arr1[0].start();
87         break;
88       case 1:
89         arr2(0,0).start();
90         break;
91       case 2:
92         arr3(0,0,0).start();
93         break;
94       case 3:
95         arrF[CkArrayIndexFancy("first")].start();
96         break;
97       case 4:
98         cid.start();
99         break;
100       case 5:
101         gid[0].start();
102         break;
103       default:
104         CkExit();
105     }
106   };
107 };
108
109 class PingG : public Group
110 {
111   CProxyElement_PingG *pp;
112   int niter;
113   int me, nbr;
114   double start_time, end_time;
115 public:
116   PingG()
117   {
118     me = CkMyPe();    
119     nbr = (me+1)%CkNumPes();
120     pp = new CProxyElement_PingG(thisgroup,nbr);
121     niter = 0;
122   }
123   PingG(CkMigrateMessage *m) {}
124   void start(void)
125   {
126     (*pp).recv();
127     start_time = CkWallTimer();
128   }
129   void recv(void)
130   {
131     if(me==0) {
132       niter++;
133       if(niter==NITER) {
134         end_time = CkWallTimer();
135         int titer = (CkNumPes()==1)?(NITER/2) : NITER;
136         CkPrintf("Roundtrip time for Groups is %lf us\n",
137                  1.0e6*(end_time-start_time)/titer);
138         mainProxy.maindone();
139       } else {
140         (*pp).recv();
141       }
142     } else {
143       (*pp).recv();
144     }
145   }
146 };
147
148 class Ping1 : public ArrayElement1D
149 {
150   CProxy_Ping1 *pp;
151   int niter;
152   double start_time, end_time;
153 public:
154   Ping1()
155   {
156     pp = new CProxy_Ping1(thisArrayID);
157     niter = 0;
158   }
159   Ping1(CkMigrateMessage *m) {}
160   void start(void)
161   {
162     (*pp)[1].recv(new PingMsg);
163     start_time = CkWallTimer();
164   }
165   void recv(PingMsg *msg)
166   {
167     if(thisIndex==0) {
168       niter++;
169       if(niter==NITER) {
170         end_time = CkWallTimer();
171         CkPrintf("Roundtrip time for 1D Arrays is %lf us\n",
172                  1.0e6*(end_time-start_time)/NITER);
173         mainProxy.maindone();
174       } else {
175         (*pp)[1].recv(msg);
176       }
177     } else {
178       (*pp)[0].recv(msg);
179     }
180   }
181 };
182
183 class Ping2 : public ArrayElement2D
184 {
185   CProxy_Ping2 *pp;
186   int niter;
187   double start_time, end_time;
188 public:
189   Ping2()
190   {
191     pp = new CProxy_Ping2(thisArrayID);
192     niter = 0;
193   }
194   Ping2(CkMigrateMessage *m) {}
195   void start(void)
196   {
197     (*pp)(0,1).recv(new PingMsg);
198     start_time = CkWallTimer();
199   }
200   void recv(PingMsg *msg)
201   {
202     if(thisIndex.y==0) {
203       niter++;
204       if(niter==NITER) {
205         end_time = CkWallTimer();
206         CkPrintf("Roundtrip time for 2D Arrays is %lf us\n",
207                  1.0e6*(end_time-start_time)/NITER);
208         mainProxy.maindone();
209       } else {
210         (*pp)(0,1).recv(msg);
211       }
212     } else {
213       (*pp)(0,0).recv(msg);
214     }
215   }
216 };
217
218 class Ping3 : public ArrayElement3D
219 {
220   CProxy_Ping3 *pp;
221   int niter;
222   double start_time, end_time;
223 public:
224   Ping3()
225   {
226     pp = new CProxy_Ping3(thisArrayID);
227     niter = 0;
228   }
229   Ping3(CkMigrateMessage *m) {}
230   void start(void)
231   {
232     (*pp)(0,0,1).recv(new PingMsg);
233     start_time = CkWallTimer();
234   }
235   void recv(PingMsg *msg)
236   {
237     if(thisIndex.z==0) {
238       niter++;
239       if(niter==NITER) {
240         end_time = CkWallTimer();
241         CkPrintf("Roundtrip time for 3D Arrays is %lf us\n",
242                  1.0e6*(end_time-start_time)/NITER);
243         mainProxy.maindone();
244       } else {
245         (*pp)(0,0,1).recv(msg);
246       }
247     } else {
248       (*pp)(0,0,0).recv(msg);
249     }
250   }
251 };
252
253 class PingF : public CBase_PingF
254 {
255   CProxy_PingF *pp;
256   int niter;
257   double start_time, end_time;
258   int first;
259 public:
260   PingF()
261   {
262     pp = new CProxy_PingF(thisArrayID);
263     niter = 0;
264     first = thisIndex.equals("first") ? 1 : 0;
265   }
266   PingF(CkMigrateMessage *m) {}
267   void start(void)
268   {
269     (*pp)[CkArrayIndexFancy("second")].recv();
270     start_time = CkWallTimer();
271   }
272   void recv(void)
273   {
274     CkArrayIndexFancy partner((char *)(first?"second" : "first"));
275     if(first) {
276       niter++;
277       if(niter==NITER) {
278         end_time = CkWallTimer();
279         CkPrintf("Roundtrip time for Fancy Arrays is %lf us\n",
280                  1.0e6*(end_time-start_time)/NITER);
281         mainProxy.maindone();
282       } else {
283         (*pp)[partner].recv();
284       }
285     } else {
286       (*pp)[partner].recv();
287     }
288   }
289 };
290
291 class PingC : public Chare
292 {
293   CProxy_PingC *pp;
294   int niter;
295   double start_time, end_time;
296   int first;
297  public:
298   PingC(void)
299   {
300     first = 0;
301   }
302   PingC(IdMsg *msg)
303   {
304     first = 1;
305     CProxy_PingC pc(msg->cid);
306     msg->cid = thishandle;
307     pc.exchange(msg);
308   }
309   PingC(CkMigrateMessage *m) {}
310   void start(void)
311   {
312     niter = 0;
313     pp->recv();
314     start_time = CkWallTimer();
315   }
316   void exchange(IdMsg *msg)
317   {
318     if(first) {
319       pp = new CProxy_PingC(msg->cid);
320       delete msg;
321     } else {
322       pp = new CProxy_PingC(msg->cid);
323       msg->cid = thishandle;
324       pp->exchange(msg);
325     }
326   }
327   void recv(void)
328   {
329     if(first) {
330       niter++;
331       if(niter==NITER) {
332         end_time = CkWallTimer();
333         CkPrintf("Roundtrip time for Chares (reuse msgs) is %lf us\n",
334                  1.0e6*(end_time-start_time)/NITER);
335         niter = 0;
336         pp->recv(new PingMsg);
337         start_time = CkWallTimer();
338       } else {
339         pp->recv();
340       }
341     } else {
342       pp->recv();
343     }
344   }
345   void recv(PingMsg *msg)
346   {
347     delete msg;
348     if(first) {
349       niter++;
350       if(niter==NITER) {
351         end_time = CkWallTimer();
352         CkPrintf("Roundtrip time for Chares (new/del msgs) is %lf us\n",
353                  1.0e6*(end_time-start_time)/NITER);
354         niter = 0;
355         pp->trecv();
356         start_time = CkWallTimer();
357       } else {
358         pp->recv(new PingMsg);
359       }
360     } else {
361       pp->recv(new PingMsg);
362     }
363   }
364   void trecv(void)
365   {
366     if(first) {
367       niter++;
368       if(niter==NITER) {
369         end_time = CkWallTimer();
370         CkPrintf("Roundtrip time for threaded Chares is %lf us\n",
371                  1.0e6*(end_time-start_time)/NITER);
372         mainProxy.maindone();
373       } else {
374         pp->trecv();
375       }
376     } else {
377       pp->trecv();
378     }
379   }
380 };
381 #include "pingpong.def.h"