msgQ test: Modify to also measure charm's underlying msgQ's enq/deq performance
[charm.git] / tests / charm++ / queue / pgm.C
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdio>
4 #include <vector>
5
6 using std::cerr;
7 using std::endl;
8 using std::sprintf;
9
10 #include "queueing.h"
11 #include "main.decl.h"
12
13 #define CmiFree free
14
15 #define RUN_TEST(f) do { \
16   ++tests; \
17   if (f()) { \
18     ++success; \
19   } else { \
20     ++fail; \
21     cerr << "Test \"" #f "\" failed" << endl; \
22   } \
23 } while (0)
24
25 // A newly created Queue should be empty, which corresponds to a
26 // length of 0
27 bool test_empty()
28 {
29   Queue q = CqsCreate();
30   bool result = (0 == CqsLength(q)) && (1 == CqsEmpty(q));
31   CqsDelete(q);
32   return result;
33 }
34
35 // Enqueueing an element should show that there is an element
36 // present. We should get the same thing back when we dequeue
37 //
38 // The queue is not allowed to dereference the void* we give it
39 bool test_one()
40 {
41   Queue q = CqsCreate();
42   void *p = 0;
43   CqsEnqueue(q, p);
44   bool result = (1 == CqsLength(q)) && (0 == CqsEmpty(q));
45   void *r;
46   CqsDequeue(q, &r);
47   result &= (r == p) 
48     && (0 == CqsLength(q)) 
49     && (1 == CqsEmpty(q));
50   CqsDelete(q);
51   return result;
52 }
53
54 // Put two in, see if we get the same two back. Order unspecified
55 bool test_two()
56 {
57   Queue q = CqsCreate();
58   void *i = 0, *j = (char *)1;
59   void *r, *s;
60   CqsEnqueue(q, i);
61   CqsEnqueue(q, j);
62   bool result = (2 == CqsLength(q));
63   CqsDequeue(q, &r);
64   CqsDequeue(q, &s);
65   result &= (r == i && s == j) || (r == j && s == i);
66   result &= 1 == CqsEmpty(q);
67   CqsDelete(q);
68   return result;
69 }
70
71 bool test_fifo()
72 {
73   Queue q = CqsCreate();
74   void *i = (char *)1, *j = (char *)2, *k = (char *)3;
75   void *r, *s, *t;
76   CqsEnqueueFifo(q, i);
77   CqsEnqueueFifo(q, j);
78   CqsEnqueueFifo(q, k);
79   CqsDequeue(q, &r);
80   CqsDequeue(q, &s);
81   CqsDequeue(q, &t);
82   bool result = (r == i) && (s == j) && (t == k);
83   CqsDelete(q);
84   return result;
85 }
86
87 bool test_lifo()
88 {
89   Queue q = CqsCreate();
90   void *i = (char *)1, *j = (char *)2, *k = (char *)3;
91   void *r, *s, *t;
92   CqsEnqueueLifo(q, i);
93   CqsEnqueueLifo(q, j);
94   CqsEnqueueLifo(q, k);
95   CqsDequeue(q, &r);
96   CqsDequeue(q, &s);
97   CqsDequeue(q, &t);
98   bool result = (r == k) && (s == j) && (t == i);
99   CqsDelete(q);
100   return result;
101 }
102
103 bool test_enqueue_mixed()
104 {
105   Queue q = CqsCreate();
106   void *i = (char *)1, *j = (char *)2, *k = (char *)3;
107   void *r, *s, *t;
108   CqsEnqueueFifo(q, i);
109   CqsEnqueueFifo(q, j);
110   CqsEnqueueLifo(q, k);
111   CqsDequeue(q, &r);
112   CqsDequeue(q, &s);
113   CqsDequeue(q, &t);
114   bool result = (r == k) && (s == i) && (t == j);
115   CqsDelete(q);
116   return result;
117 }
118
119 static bool findEntry(void ** const e, int num, void * const t)
120 {
121     for (int i = 0; i < num; ++i)
122     {
123         if (e[i] == t)
124             return true;
125     }
126     return false;
127 }
128
129 bool test_enumerate()
130 {
131   Queue q = CqsCreate();
132   void *i = (char *)1, *j = (char *)2, *k = (char *)3;
133   void **e;
134   CqsEnqueueFifo(q, i);
135   CqsEnqueueFifo(q, j);
136   CqsEnqueueLifo(q, k);
137   CqsEnumerateQueue(q, &e);
138   int n = CqsLength(q);
139   bool result = findEntry(e, n, i) && findEntry(e, n, j) && findEntry(e, n, k);
140   CmiFree(e);
141   CqsDelete(q);
142   return result;
143 }
144
145 bool test_general_fifo()
146 {
147   Queue q = CqsCreate();
148   void *i = (char *)1, *j = (char *)2, *k = (char *)3;
149   CqsEnqueueGeneral(q, i, CQS_QUEUEING_FIFO, 1, 0);
150   CqsEnqueueGeneral(q, j, CQS_QUEUEING_FIFO, 2, 0);
151   CqsEnqueueGeneral(q, k, CQS_QUEUEING_FIFO, 42, 0);
152   void *r, *s, *t;
153   CqsDequeue(q, &r);
154   CqsDequeue(q, &s);
155   CqsDequeue(q, &t);
156   bool result = (r == i) && (s == j) && (t == k);
157   CqsDelete(q);
158   return result;
159 }
160
161 bool test_general_ififo()
162 {
163   Queue q = CqsCreate();
164   void *i = (char *)1, *j = (char *)2, *k = (char *)3;
165   unsigned int a = -1, b = 0, c = 1;
166   CqsEnqueueGeneral(q, i, CQS_QUEUEING_IFIFO, 8*sizeof(int), &c);
167   CqsEnqueueGeneral(q, j, CQS_QUEUEING_IFIFO, 8*sizeof(int), &b);
168   CqsEnqueueGeneral(q, k, CQS_QUEUEING_IFIFO, 8*sizeof(int), &a);
169   void *r, *s, *t;
170   CqsDequeue(q, &r);
171   CqsDequeue(q, &s);
172   CqsDequeue(q, &t);
173   bool result = (r == k) && (s == j) && (t == i);
174   CqsDelete(q);
175   return result;
176 }
177
178 double timePerOp_general_ififo(int qBaseSize = 256)
179 {
180   Queue q = CqsCreate();
181   int qBatchSize = 1<<4;
182   int numIters   = 1<<16;
183
184   std::vector<char> msgs(qBaseSize + qBatchSize);
185   std::vector<unsigned int> prios(qBaseSize + qBatchSize);
186
187   for (int i = 0; i < qBaseSize + qBatchSize; i++)
188       prios[i] = std::rand();
189
190   for (int i = 0; i < qBaseSize; i++)
191       CqsEnqueueGeneral(q, (void*)&msgs[i], CQS_QUEUEING_IFIFO, 8*sizeof(int), &prios[i]);
192
193   double startTime = CmiWallTimer();
194   for (int i = 0; i < numIters; i++)
195   {
196       for (int j = qBaseSize; j < qBaseSize+qBatchSize; j++)
197         CqsEnqueueGeneral(q, (void*)&msgs[j], CQS_QUEUEING_IFIFO, 8*sizeof(int), &prios[j]);
198       void *m;
199       for (int j = qBaseSize; j < qBaseSize+qBatchSize; j++)
200         CqsDequeue(q, &m);
201   }
202
203   CqsDelete(q);
204   return 1000000 * (CmiWallTimer() - startTime) / (numIters * qBatchSize * 2);
205 }
206
207
208 bool perftest_general_ififo()
209 {
210   CkPrintf("Reporting time per enqueue / dequeue operation for charm's underlying mixed priority queue\n");
211   CkPrintf("\n  Q length     time/op(us)\n");
212   for (int i = 16; i <= 1024; i *= 2)
213     CkPrintf("%10d %15f\n", i, timePerOp_general_ififo(i));
214
215   return true;
216 }
217
218 #if 0
219 // Template for new harness-driven tests
220 bool test_foo()
221 {
222   Queue q = CqsCreate();
223   
224   bool result = ;
225   CqsDelete(q);
226   return result;
227 }
228 #endif
229
230 struct main : public CBase_main
231 {
232   main(CkArgMsg *)
233   {
234     int tests = 0, success = 0, fail = 0;
235     char message[100];
236
237     RUN_TEST(test_empty);
238     RUN_TEST(test_one);
239     RUN_TEST(test_two);
240     RUN_TEST(test_fifo);
241     RUN_TEST(test_lifo);
242     RUN_TEST(test_enqueue_mixed);
243     RUN_TEST(test_enumerate);
244     RUN_TEST(test_general_fifo);
245     RUN_TEST(test_general_ififo);
246     RUN_TEST(perftest_general_ififo);
247
248     if (fail) {
249       sprintf(message, "%d/%d tests failed\n", fail, tests);
250       CkAbort(message);
251     }
252     else {
253       CkPrintf("All %d tests passed\n", tests);
254       CkExit();
255     }
256   }
257
258 };
259
260 #include "main.def.h"