e053eebb1a28c5f9f945025f86ce95fc17ea388e
[charm.git] / tests / converse / commbench / pingpong.c
1 #include <stdlib.h>
2 #include <converse.h>
3 #include "commbench.h"
4
5 #define pva CpvAccess
6 #define pvd CpvStaticDeclare
7 #define pvi CpvInitialize
8
9 static struct testdata {
10   int size;
11   int numiter;
12 } sizes[] = {
13  {16,      1},
14  {32,      4000},
15  {128,      4000},
16  {256,     1000},
17  {512,     1000},
18  {1024,    1000},
19  {2048,    1000},
20  {4096,    1000},
21  {8192,    1000},
22  {16384,   1000},
23  {32768,   1000},
24  {65536,   100},
25  {131072,   40},
26  {524288,   40},
27  {1048576, 10},
28  {4194304,  10},
29  {8388608,  10},
30  {16777216,  4},
31 /*
32  {33554432,  4},
33 */
34     {-1,      -1},
35 };
36
37 typedef struct message_{
38   char core[CmiMsgHeaderSizeBytes];
39   int srcpe;
40   int idx;
41   int data[1];
42 } Message;
43
44 static void fillMessage(Message *msg)
45 {
46   int i, size, items;
47   size = sizes[msg->idx].size + sizeof(double);
48   items = size/sizeof(double);
49   for(i=0;i<items;i++)
50     msg->data[i] = i+0x1234;
51 }
52
53 static void checkMessage(Message *msg)
54 {
55   int i, size, items;
56   size = sizes[msg->idx].size + sizeof(double);
57   items = size/sizeof(double);
58   for(i=0;i<items;i++) {
59     if(msg->data[i] != (i+0x1234))
60       CmiAbort("[pingpong] Data corrupted. Run megacon !!\n");
61   }
62 }
63
64 typedef struct Time_{
65   char core[CmiMsgHeaderSizeBytes];
66   int srcNode;
67   double data[1];
68 } TimeMessage;
69
70 pvd(int, nextIter);
71 pvd(int, nextSize);
72 pvd(int, nextNbr); 
73
74 pvd(double, starttime);
75 pvd(double, endtime);
76 pvd(double **, times);/* stores times for all nbrs and sizes */
77 pvd(int *, nodeList); /* stores nums of pes rank 0 on all nodes*/
78 pvd(double *, gavg);
79 pvd(double *, gmax);
80 pvd(double *, gmin);
81 pvd(int *, gmaxSrc);
82 pvd(int *, gmaxDest);
83 pvd(int *, gminSrc);
84 pvd(int *, gminDest);
85
86 pvd(int, numSizes);    /* how many test sizes exist */
87 pvd(int, numRecv);
88
89 pvd(int, timeHandler);
90 pvd(int, nodeHandler);
91 pvd(int, nbrHandler);
92 pvd(int, sizeHandler);
93 pvd(int, iterHandler);
94 pvd(int, bounceHandler);
95
96 static void recvTime(TimeMessage *msg)
97 {
98   EmptyMsg m;
99   int i, j;
100   double time;
101
102   pva(numRecv)++;
103   for(i=0;i<CmiNumPes();i++) {
104     if(i==msg->srcNode)
105       continue;
106     for(j=0;j<pva(numSizes);j++) {
107       time = *(msg->data+i*pva(numSizes)+j);
108       pva(gavg)[j] += time;
109       if(time > pva(gmax)[j]) {
110         pva(gmax)[j] = time;
111         pva(gmaxSrc)[j] = msg->srcNode;
112         pva(gmaxDest)[j] = i;
113       }
114       if(time < pva(gmin)[j]) {
115         pva(gmin)[j] = time;
116         pva(gminSrc)[j] = msg->srcNode;
117         pva(gminDest)[j] = i;
118       }
119     }
120   }
121   if(pva(numRecv)==CmiNumPes()){
122     for(j=0;j<pva(numSizes);j++)
123       pva(gavg)[j] /= (CmiNumPes()*(CmiNumPes()-1));
124     CmiPrintf("[pingpong] CmiSyncSend\n");
125     for(j=0;j<pva(numSizes);j++) {
126       CmiPrintf("[pingpong] size=%d\taverageTime=%le seconds\n",
127                             sizes[j].size, pva(gavg)[j]);
128       CmiPrintf("[pingpong] size=%d\tmaxTime=%le seconds\t[%d->%d]\n",
129                   sizes[j].size, pva(gmax)[j],pva(gmaxSrc)[j],pva(gmaxDest)[j]);
130       CmiPrintf("[pingpong] size=%d\tminTime=%le seconds\t[%d->%d]\n",
131                   sizes[j].size, pva(gmin)[j],pva(gminSrc)[j],pva(gminDest)[j]);
132     }
133     CmiSetHandler(&m, pva(ack_handler));
134     CmiSyncSend(0, sizeof(EmptyMsg), &m);
135   }
136   CmiFree(msg);
137 }
138
139 static void startNextNode(EmptyMsg *msg)
140 {
141   EmptyMsg m;
142   CmiFree(msg);
143   if((CmiMyPe()+1) != CmiNumPes()) {
144     CmiSetHandler(&m, pva(nbrHandler));
145     CmiSyncSend(pva(nodeList)[CmiMyPe()+1], sizeof(EmptyMsg), &m);
146   }
147 }
148
149 static void startNextNbr(EmptyMsg *msg)
150 {
151   EmptyMsg m;
152   TimeMessage *tm;
153   int i, size;
154
155   CmiFree(msg);
156   pva(nextNbr)++;
157   if(pva(nextNbr) == CmiMyPe()) {
158     CmiSetHandler(&m, pva(nbrHandler));
159     CmiSyncSend(CmiMyPe(), sizeof(EmptyMsg), &m);
160     return;
161   }
162   if(pva(nextNbr) == CmiNumPes()) {
163     pva(nextNbr) = -1;
164     CmiSetHandler(&m, pva(nodeHandler));
165     CmiSyncSend(CmiMyPe(), sizeof(EmptyMsg), &m);
166     size = sizeof(TimeMessage)+pva(numSizes)*CmiNumPes()*sizeof(double);
167     tm = (TimeMessage *) CmiAlloc(size);
168     for(i=0;i<CmiNumPes();i++)
169       memcpy(tm->data+i*pva(numSizes),pva(times)[i],
170              sizeof(double)*pva(numSizes));
171     tm->srcNode = CmiMyPe();
172     CmiSetHandler(tm, pva(timeHandler));
173     CmiSyncSendAndFree(0, size, tm);
174   } else {
175     CmiSetHandler(&m, pva(sizeHandler));
176     CmiSyncSend(CmiMyPe(), sizeof(EmptyMsg), &m);
177   }
178 }
179
180 static void startNextSize(EmptyMsg *msg)
181 {
182   EmptyMsg m;
183   Message *mm;
184
185   pva(nextSize)++;
186   if(pva(nextSize) == pva(numSizes)) {
187     pva(nextSize) = -1;
188     CmiSetHandler(&m, pva(nbrHandler));
189     CmiSyncSend(CmiMyPe(), sizeof(EmptyMsg), &m);
190   } else {
191     int size = sizeof(Message)+sizes[pva(nextSize)].size;
192     mm = (Message *) CmiAlloc(size);
193     mm->srcpe = CmiMyPe();
194     mm->idx = pva(nextSize);
195     CmiSetHandler(mm, pva(iterHandler));
196     fillMessage(mm);
197     CmiSyncSendAndFree(CmiMyPe(), size, mm);
198     pva(starttime) = CmiWallTimer();
199   }
200   CmiFree(msg);
201 }
202
203 static void startNextIter(Message *msg)
204 {
205   EmptyMsg m;
206
207   pva(nextIter)++;
208   if(pva(nextIter) > sizes[pva(nextSize)].numiter) {
209     pva(endtime) = CmiWallTimer();
210     checkMessage(msg);
211     pva(times)[pva(nextNbr)][pva(nextSize)] =
212       (pva(endtime) - pva(starttime))/(2.0*sizes[pva(nextSize)].numiter);
213     pva(nextIter) = -1;
214     CmiSetHandler(&m, pva(sizeHandler));
215     CmiSyncSend(CmiMyPe(), sizeof(EmptyMsg), &m);
216     CmiFree(msg);
217   } else {
218     CmiSetHandler(msg, pva(bounceHandler));
219     CmiSyncSendAndFree(pva(nextNbr), sizeof(Message)+sizes[msg->idx].size, msg);
220   }
221 }
222
223 static void bounceMessage(Message *msg)
224 {
225   CmiSetHandler(msg, pva(iterHandler));
226   CmiSyncSendAndFree(msg->srcpe, sizeof(Message)+sizes[msg->idx].size, msg);
227 }
228
229 void pingpong_init(void)
230 {
231   EmptyMsg m;
232
233   if(CmiNumPes()==1) {
234     CmiPrintf("[pingpong] This benchmark requires > 1 nodes.\n");
235     CmiSetHandler(&m, pva(ack_handler));
236     CmiSyncSend(0, sizeof(EmptyMsg), &m);
237     return;
238   }
239   CmiSetHandler(&m, pva(nbrHandler));
240   CmiSyncSend(0, sizeof(EmptyMsg), &m);
241 }
242
243 void pingpong_moduleinit(void)
244 {
245   int i,j;
246   pvi(int, numRecv);
247   pva(numRecv) = 0;
248   pvi(int, nextIter);
249   pva(nextIter) = -1;
250   pvi(int, nextSize);
251   pva(nextSize) = -1;
252   pvi(int, nextNbr);
253   pva(nextNbr) = -1;
254   pvi(double, starttime);
255   pva(starttime) = 0.0;
256   pvi(double, endtime);
257   pva(endtime) = 0.0;
258   pvi(int, numSizes);
259   for(i=0; sizes[i].size != (-1); i++);
260   pva(numSizes) = i;
261   pvi(double **, times);
262   pva(times) = (double **) malloc(CmiNumPes()*sizeof(double *));
263   for(i=0;i<CmiNumPes();i++)
264     pva(times)[i] = (double *) malloc(pva(numSizes)*sizeof(double));
265   for(i=0;i<CmiNumPes();i++)
266     for(j=0;j<pva(numSizes);j++)
267       pva(times)[i][j] = 0.0;
268   pvi(int *, nodeList);
269   pva(nodeList) = (int *) malloc(CmiNumPes()*sizeof(int));
270   for(i=0;i<CmiNumPes();i++)
271     pva(nodeList)[i] = i; /*CmiNodeFirst(i);*/
272   pvi(double *, gavg);
273   pva(gavg) = (double *) malloc(sizeof(double)*pva(numSizes));
274   pvi(double *, gmax);
275   pva(gmax) = (double *) malloc(sizeof(double)*pva(numSizes));
276   pvi(double *, gmin);
277   pva(gmin) = (double *) malloc(sizeof(double)*pva(numSizes));
278   pvi(int *, gmaxSrc);
279   pva(gmaxSrc) = (int *) malloc(sizeof(int)*pva(numSizes));
280   pvi(int *, gmaxDest);
281   pva(gmaxDest) = (int *) malloc(sizeof(int)*pva(numSizes));
282   pvi(int *, gminSrc);
283   pva(gminSrc) = (int *) malloc(sizeof(int)*pva(numSizes));
284   pvi(int *, gminDest);
285   pva(gminDest) = (int *) malloc(sizeof(int)*pva(numSizes));
286   for(i=0;i<pva(numSizes);i++) {
287     pva(gavg)[i] = 0.0;
288     pva(gmax)[i] = 0.0;
289     pva(gmin)[i] = 1000000000.0;
290     pva(gmaxSrc)[i] = 0;
291     pva(gmaxDest)[i] = 0;
292     pva(gminSrc)[i] = 0;
293     pva(gminDest)[i] = 0;
294   }
295   pvi(int, timeHandler);
296   pva(timeHandler) = CmiRegisterHandler((CmiHandler)recvTime);
297   pvi(int, nodeHandler);
298   pva(nodeHandler) = CmiRegisterHandler((CmiHandler)startNextNode);
299   pvi(int, nbrHandler);
300   pva(nbrHandler) = CmiRegisterHandler((CmiHandler)startNextNbr);
301   pvi(int, sizeHandler);
302   pva(sizeHandler) = CmiRegisterHandler((CmiHandler)startNextSize);
303   pvi(int, iterHandler);
304   pva(iterHandler) = CmiRegisterHandler((CmiHandler)startNextIter);
305   pvi(int, bounceHandler);
306   pva(bounceHandler) = CmiRegisterHandler((CmiHandler)bounceMessage);
307 }