added threaded array
[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         niter=0;
179         start_time = CkWallTimer();
180         (*pp)[0].trecv(msg);
181       } else {
182         (*pp)[1].recv(msg);
183       }
184     } else {
185       (*pp)[0].recv(msg);
186     }
187   }
188   void trecv(PingMsg *msg)
189   {
190     if(thisIndex==0) {
191       niter++;
192       if(niter==NITER) {
193         end_time = CkWallTimer();
194         CkPrintf("Roundtrip time for 1D threaded Arrays is %lf us\n",
195                  1.0e6*(end_time-start_time)/NITER);
196         mainProxy.maindone();
197       } else {
198         (*pp)[1].trecv(msg);
199       }
200     } else {
201       (*pp)[0].trecv(msg);
202     }
203   }
204 };
205
206 class Ping2 : public ArrayElement2D
207 {
208   CProxy_Ping2 *pp;
209   int niter;
210   double start_time, end_time;
211 public:
212   Ping2()
213   {
214     pp = new CProxy_Ping2(thisArrayID);
215     niter = 0;
216   }
217   Ping2(CkMigrateMessage *m) {}
218   void start(void)
219   {
220     (*pp)(0,1).recv(new PingMsg);
221     start_time = CkWallTimer();
222   }
223   void recv(PingMsg *msg)
224   {
225     if(thisIndex.y==0) {
226       niter++;
227       if(niter==NITER) {
228         end_time = CkWallTimer();
229         CkPrintf("Roundtrip time for 2D Arrays is %lf us\n",
230                  1.0e6*(end_time-start_time)/NITER);
231         mainProxy.maindone();
232       } else {
233         (*pp)(0,1).recv(msg);
234       }
235     } else {
236       (*pp)(0,0).recv(msg);
237     }
238   }
239 };
240
241 class Ping3 : public ArrayElement3D
242 {
243   CProxy_Ping3 *pp;
244   int niter;
245   double start_time, end_time;
246 public:
247   Ping3()
248   {
249     pp = new CProxy_Ping3(thisArrayID);
250     niter = 0;
251   }
252   Ping3(CkMigrateMessage *m) {}
253   void start(void)
254   {
255     (*pp)(0,0,1).recv(new PingMsg);
256     start_time = CkWallTimer();
257   }
258   void recv(PingMsg *msg)
259   {
260     if(thisIndex.z==0) {
261       niter++;
262       if(niter==NITER) {
263         end_time = CkWallTimer();
264         CkPrintf("Roundtrip time for 3D Arrays is %lf us\n",
265                  1.0e6*(end_time-start_time)/NITER);
266         mainProxy.maindone();
267       } else {
268         (*pp)(0,0,1).recv(msg);
269       }
270     } else {
271       (*pp)(0,0,0).recv(msg);
272     }
273   }
274 };
275
276 class PingF : public CBase_PingF
277 {
278   CProxy_PingF *pp;
279   int niter;
280   double start_time, end_time;
281   int first;
282 public:
283   PingF()
284   {
285     pp = new CProxy_PingF(thisArrayID);
286     niter = 0;
287     first = thisIndex.equals("first") ? 1 : 0;
288   }
289   PingF(CkMigrateMessage *m) {}
290   void start(void)
291   {
292     (*pp)[CkArrayIndexFancy("second")].recv();
293     start_time = CkWallTimer();
294   }
295   void recv(void)
296   {
297     CkArrayIndexFancy partner((char *)(first?"second" : "first"));
298     if(first) {
299       niter++;
300       if(niter==NITER) {
301         end_time = CkWallTimer();
302         CkPrintf("Roundtrip time for Fancy Arrays is %lf us\n",
303                  1.0e6*(end_time-start_time)/NITER);
304         mainProxy.maindone();
305       } else {
306         (*pp)[partner].recv();
307       }
308     } else {
309       (*pp)[partner].recv();
310     }
311   }
312 };
313
314 class PingC : public Chare
315 {
316   CProxy_PingC *pp;
317   int niter;
318   double start_time, end_time;
319   int first;
320  public:
321   PingC(void)
322   {
323     first = 0;
324   }
325   PingC(IdMsg *msg)
326   {
327     first = 1;
328     CProxy_PingC pc(msg->cid);
329     msg->cid = thishandle;
330     pc.exchange(msg);
331   }
332   PingC(CkMigrateMessage *m) {}
333   void start(void)
334   {
335     niter = 0;
336     pp->recvReuse(new PingMsg);
337     start_time = CkWallTimer();
338   }
339   void exchange(IdMsg *msg)
340   {
341     if(first) {
342       pp = new CProxy_PingC(msg->cid);
343       delete msg;
344     } else {
345       pp = new CProxy_PingC(msg->cid);
346       msg->cid = thishandle;
347       pp->exchange(msg);
348     }
349   }
350   void recvReuse(PingMsg *msg)
351   {
352     if(first) {
353       niter++;
354       if(niter==NITER) {
355         end_time = CkWallTimer();
356         CkPrintf("Roundtrip time for Chares (reuse msgs) is %lf us\n",
357                  1.0e6*(end_time-start_time)/NITER);
358         niter = 0;
359         delete msg;
360         pp->recv(new PingMsg);
361         start_time = CkWallTimer();
362       } else {
363         pp->recvReuse(msg);
364       }
365     } else {
366       pp->recvReuse(msg);
367     }
368   }
369   void recv(PingMsg *msg)
370   {
371     delete msg;
372     if(first) {
373       niter++;
374       if(niter==NITER) {
375         end_time = CkWallTimer();
376         CkPrintf("Roundtrip time for Chares (new/del msgs) is %lf us\n",
377                  1.0e6*(end_time-start_time)/NITER);
378         niter = 0;
379         pp->trecv();
380         start_time = CkWallTimer();
381       } else {
382         pp->recv(new PingMsg);
383       }
384     } else {
385       pp->recv(new PingMsg);
386     }
387   }
388   void trecv(void)
389   {
390     if(first) {
391       niter++;
392       if(niter==NITER) {
393         end_time = CkWallTimer();
394         CkPrintf("Roundtrip time for threaded Chares is %lf us\n",
395                  1.0e6*(end_time-start_time)/NITER);
396         mainProxy.maindone();
397       } else {
398         pp->trecv();
399       }
400     } else {
401       pp->trecv();
402     }
403   }
404 };
405 #include "pingpong.def.h"