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