This source file includes following definitions.
- thread_test
- thread_test_exhaust
- check_fifo_consistency
- main
1
2
3
4
5
6
7
8
9
10
11
12
13 #include "opal_config.h"
14 #include <assert.h>
15
16 #include "support.h"
17 #include "opal/class/opal_fifo.h"
18 #include "opal/runtime/opal.h"
19 #include "opal/constants.h"
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stddef.h>
24
25 #include <sys/time.h>
26
27 #define OPAL_FIFO_TEST_THREAD_COUNT 8
28 #define ITERATIONS 1000000
29 #define ITEM_COUNT 100
30 #define ITEMS_PER_LOOP 30
31
32 #if !defined(timersub)
33 #define timersub(a, b, r) \
34 do { \
35 (r)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
36 if ((a)->tv_usec < (b)->tv_usec) { \
37 (r)->tv_sec--; \
38 (a)->tv_usec += 1000000; \
39 } \
40 (r)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
41 } while (0)
42 #endif
43
44 static void *thread_test (void *arg) {
45 opal_fifo_t *fifo = (opal_fifo_t *) arg;
46 opal_list_item_t *item;
47 struct timeval start, stop, total;
48 double timing;
49
50 gettimeofday (&start, NULL);
51 for (int i = 0 ; i < ITERATIONS ; ++i) {
52 item = opal_fifo_pop_atomic (fifo);
53 if (NULL != item) {
54 (void) opal_fifo_push_atomic (fifo, item);
55 }
56 }
57 gettimeofday (&stop, NULL);
58
59 timersub(&stop, &start, &total);
60
61 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) ITERATIONS;
62
63 printf ("Atomics thread finished. Time: %d s %d us %d nsec/poppush\n", (int) total.tv_sec,
64 (int)total.tv_usec, (int)(timing / 1e-9));
65
66 return NULL;
67 }
68
69 static void *thread_test_exhaust (void *arg) {
70 opal_fifo_t *fifo = (opal_fifo_t *) arg;
71 opal_list_item_t *items[ITEMS_PER_LOOP];
72 struct timeval start, stop, total;
73 int item_count = 0;
74 double timing;
75
76 gettimeofday (&start, NULL);
77
78 for (int i = 0 ; i < ITERATIONS ; i += ITEMS_PER_LOOP) {
79 for (int j = 0 ; j < ITEMS_PER_LOOP ; ++j) {
80 items[j] = opal_fifo_pop_atomic (fifo);
81 if (items[j]) {
82 ++item_count;
83 }
84 }
85
86 for (int j = 0 ; j < ITEMS_PER_LOOP ; ++j) {
87 if (items[j]) {
88 (void) opal_fifo_push_atomic (fifo, items[j]);
89 }
90 }
91 }
92
93 gettimeofday (&stop, NULL);
94
95 timersub(&stop, &start, &total);
96
97 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) item_count;
98
99 fprintf (stderr, "Exhaustive atomics thread finished. Popped %d items. Time: %d s %d us %d nsec/poppush\n", item_count,
100 (int) total.tv_sec, (int)total.tv_usec, (int)(timing / 1e-9));
101
102 return NULL;
103 }
104
105 static bool check_fifo_consistency (opal_fifo_t *fifo, int expected_count)
106 {
107 volatile opal_list_item_t *volatile item;
108 int count;
109
110 for (count = 0, item = fifo->opal_fifo_head.data.item ; item != &fifo->opal_fifo_ghost ;
111 item = opal_list_get_next(item), count++);
112
113 return count == expected_count;
114 }
115
116 int main (int argc, char *argv[]) {
117 pthread_t threads[OPAL_FIFO_TEST_THREAD_COUNT];
118 opal_list_item_t *item, *prev, *item2;
119 struct timeval start, stop, total;
120 opal_fifo_t fifo;
121 bool success;
122 double timing;
123 int rc;
124
125 rc = opal_init_util (&argc, &argv);
126 test_verify_int(OPAL_SUCCESS, rc);
127 if (OPAL_SUCCESS != rc) {
128 test_finalize();
129 exit (1);
130 }
131
132 test_init("opal_fifo_t");
133
134 OBJ_CONSTRUCT(&fifo, opal_fifo_t);
135
136 item = OBJ_NEW(opal_list_item_t);
137 prev = opal_fifo_push_st (&fifo, item);
138 if (&fifo.opal_fifo_ghost == prev) {
139 test_success ();
140 } else {
141 test_failure (" opal_fifo_push_st on empty fifo");
142 }
143
144 item2 = opal_fifo_pop_st (&fifo);
145 if (item == item2) {
146 test_success ();
147 } else {
148 test_failure (" opal_fifo_pop_st");
149 }
150
151 OBJ_RELEASE(item);
152
153 for (int i = 0 ; i < ITEM_COUNT ; ++i) {
154 item = OBJ_NEW(opal_list_item_t);
155 item->item_free = 0;
156 opal_fifo_push_st (&fifo, item);
157 }
158
159 if (check_fifo_consistency (&fifo, ITEM_COUNT)) {
160 test_success ();
161 } else {
162 test_failure (" opal_fifo_push_st(multiple items)");
163 }
164
165 gettimeofday (&start, NULL);
166 for (int i = 0 ; i < ITERATIONS ; ++i) {
167 item = opal_fifo_pop_st (&fifo);
168 (void) opal_fifo_push_st (&fifo, item);
169 }
170 gettimeofday (&stop, NULL);
171
172 timersub(&stop, &start, &total);
173
174 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) ITERATIONS;
175
176 if (check_fifo_consistency (&fifo, ITEM_COUNT)) {
177 test_success ();
178 } else {
179 test_failure (" fifo push/pop");
180 }
181
182 printf ("Single thread test. Time: %d s %d us %d nsec/poppush\n", (int) total.tv_sec,
183 (int)total.tv_usec, (int)(timing / 1e-9));
184
185 thread_test (&fifo);
186
187 if (check_fifo_consistency (&fifo, ITEM_COUNT)) {
188 test_success ();
189 } else {
190 test_failure (" fifo push/pop single-threaded with atomics");
191 }
192
193 gettimeofday (&start, NULL);
194 for (int i = 0 ; i < OPAL_FIFO_TEST_THREAD_COUNT ; ++i) {
195 pthread_create (threads + i, NULL, thread_test, &fifo);
196 }
197
198 for (int i = 0 ; i < OPAL_FIFO_TEST_THREAD_COUNT ; ++i) {
199 void *ret;
200
201 pthread_join (threads[i], &ret);
202 }
203 gettimeofday (&stop, NULL);
204
205 timersub(&stop, &start, &total);
206
207 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) (ITERATIONS * OPAL_FIFO_TEST_THREAD_COUNT);
208
209 if (check_fifo_consistency (&fifo, ITEM_COUNT)) {
210 test_success ();
211 } else {
212 test_failure (" fifo push/pop multi-threaded with atomics");
213 }
214
215 printf ("All threads finished. Thread count: %d Time: %d s %d us %d nsec/poppush\n",
216 OPAL_FIFO_TEST_THREAD_COUNT, (int) total.tv_sec, (int)total.tv_usec, (int)(timing / 1e-9));
217
218
219 gettimeofday (&start, NULL);
220 for (int i = 0 ; i < OPAL_FIFO_TEST_THREAD_COUNT ; ++i) {
221 pthread_create (threads + i, NULL, thread_test_exhaust, &fifo);
222 }
223
224 for (int i = 0 ; i < OPAL_FIFO_TEST_THREAD_COUNT ; ++i) {
225 void *ret;
226
227 pthread_join (threads[i], &ret);
228 }
229 gettimeofday (&stop, NULL);
230
231 timersub(&stop, &start, &total);
232
233 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) (ITERATIONS * OPAL_FIFO_TEST_THREAD_COUNT);
234
235 if (check_fifo_consistency (&fifo, ITEM_COUNT)) {
236 test_success ();
237 } else {
238 test_failure (" fifo push/pop multi-threaded with atomics when there are insufficient items");
239 }
240
241 printf ("All threads finished. Thread count: %d Time: %d s %d us %d nsec/poppush\n",
242 OPAL_FIFO_TEST_THREAD_COUNT, (int) total.tv_sec, (int)total.tv_usec, (int)(timing / 1e-9));
243
244 success = true;
245 for (int i = 0 ; i < ITEM_COUNT ; ++i) {
246 item = opal_fifo_pop_st (&fifo);
247 if (NULL == item) {
248 success = false;
249 break;
250 }
251 OBJ_RELEASE(item);
252 }
253
254 if (success) {
255 test_success ();
256 } else {
257 test_failure (" fifo pop all items");
258 }
259
260 OBJ_DESTRUCT(&fifo);
261
262 opal_finalize_util ();
263
264 return test_finalize ();
265 }