e536b16319acaf45d4791c9034d136a65b3ba707
[charm.git] / tests / ampi / isomalloc / test.C
1 #ifndef __STDC_FORMAT_MACROS
2 # define __STDC_FORMAT_MACROS
3 #endif
4 #ifndef __STDC_LIMIT_MACROS
5 # define __STDC_LIMIT_MACROS
6 #endif
7
8 #include <cstdint>
9 #include <cstdlib>
10 #include <cstdio>
11 #include <random>
12 #include <chrono>
13 #include <algorithm>
14 #include <functional>
15 #include <type_traits>
16
17 // for getrusage
18 #include <sys/time.h>
19 #include <sys/resource.h>
20
21 #include "mpi.h"
22
23 #define STRINGIZE(x) #x
24 #define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
25 #define isomalloc_method_str STRINGIZE_VALUE_OF(isomalloc_method)
26
27 static const uint32_t primes[] =
28 {
29   2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
30   73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
31   157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
32   239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
33   331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
34   421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
35   509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
36   613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
37   709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
38   821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
39   919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
40   1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,
41   1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201,
42   1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
43   1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409,
44   1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487,
45   1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579,
46   1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667,
47   1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777,
48   1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
49   1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993,
50   1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083,
51   2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179,
52   2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
53   2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381,
54   2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473,
55   2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609,
56   2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
57   2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789,
58   2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887,
59   2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001,
60   3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119,
61   3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229,
62   3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
63   3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457,
64   3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
65   3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637,
66   3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739,
67   3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853,
68   3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947,
69   3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073,
70   4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
71   4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273,
72   4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
73   4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517,
74   4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639,
75   4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733,
76   4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871,
77   4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969,
78   4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077,
79   5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189,
80   5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309,
81   5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431,
82   5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
83   5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651,
84   5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
85   5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851,
86   5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981,
87   5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091,
88   6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211,
89   6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311,
90   6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397,
91   6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553,
92   6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
93   6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781,
94   6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883,
95   6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991,
96   6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
97   7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237,
98   7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369,
99   7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507,
100   7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589,
101   7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699,
102   7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
103   7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937,
104   7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087,
105   8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209,
106   8219, 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297,
107   8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431,
108   8443, 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573,
109   8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681,
110   8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, 8753, 8761, 8779,
111   8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887,
112   8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
113   9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137,
114   9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241,
115   9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371,
116   9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463,
117   9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601,
118   9613, 9619, 9623, 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719,
119   9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817,
120   9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929,
121   9931, 9941, 9949, 9967, 9973,
122 };
123
124 static const uint32_t largeprimes[] =
125 {
126   143687, 266083, 393073, 523417, 656683, 791447, 927853, 1066909, 1205653,
127   1346567, 1488133, 1630987, 1774937, 1918439, 2063573, 2209499, 2356573,
128   2503597, 2650931, 2799451, 2948161, 3097141, 3246119, 3396661, 3548471,
129   3698881, 3849943, 4002547, 4154791, 4307453, 4459951, 4613237, 4766999,
130   4920613, 5074633, 5229331, 5383601, 5539363, 5695831, 5851717, 6007247,
131   6163567, 6319483, 6477301, 6633877, 6791437, 6947753, 7104341, 7263143,
132   7421383, 7580459, 7738559, 7896949, 8056423, 8215633, 8375273, 8534489,
133   8693653, 8853359, 9014101, 9174793, 9334487, 9495601, 9655759, 9817057,
134   9979111, 10140307,
135 };
136
137 template <typename T, size_t N>
138 static inline constexpr size_t countof(T const (&)[N]) noexcept
139 {
140   return N;
141 }
142
143 static inline void request_migration()
144 {
145   AMPI_Migrate(AMPI_INFO_LB_SYNC);
146 }
147
148 using clock_type = typename std::conditional<
149   std::chrono::high_resolution_clock::is_steady,
150   std::chrono::high_resolution_clock, std::chrono::steady_clock>::type;
151 using time_point = typename std::chrono::time_point<clock_type>;
152 using duration_type = typename std::chrono::duration<unsigned long long, std::nano>;
153
154 static void malloc_stress(int rank, int p, uint32_t randomseed)
155 {
156   // This function avoids heap allocations other than the test itself.
157
158   std::mt19937 generator{randomseed};
159
160   static constexpr size_t maxallocs = 2048;
161   static constexpr size_t maxsegments = 8;
162   static constexpr size_t maxtests = 32;
163
164   struct alloc_type
165   {
166     unsigned char *ptr;
167     unsigned int size;
168   };
169   alloc_type allocations[maxallocs]{};
170   alloc_type * allocation_queue[maxallocs*2]{};
171
172   unsigned int segments[maxsegments]{}; // segment boundaries
173
174   struct test_type
175   {
176     const char *description1, *description2;
177     unsigned long long duration_count;
178   };
179   test_type tests[maxtests]{};
180
181   size_t numallocs = 0;
182   size_t numsegments = 1;
183   segments[0] = 0;
184
185
186   static_assert(countof(primes) + 3*countof(largeprimes) <= maxallocs, "increase maxallocs");
187
188   for (size_t i = rank; i < countof(primes); i += p)
189   {
190     allocations[numallocs++].size = primes[i];
191   }
192   segments[numsegments++] = numallocs;
193
194   for (size_t i = rank; i < countof(largeprimes); i += p)
195   {
196     allocations[numallocs++].size = largeprimes[i];
197   }
198   segments[numsegments++] = numallocs;
199
200   for (size_t i = rank; i < countof(largeprimes); i += p)
201   {
202     allocations[numallocs++].size = primes[countof(primes)-1-i];
203     allocations[numallocs++].size = largeprimes[i];
204   }
205   segments[numsegments++] = numallocs;
206
207
208   const size_t queuesize = numallocs * 2;
209
210 #ifdef MIGRATION_OVERKILL
211   const size_t migrationinterval = numallocs / 31; // prime number divisor
212   size_t eventnum = 0;
213 #endif
214
215   size_t testnum = 0;
216
217   auto alloc_loop = [&](const size_t a_begin, const size_t a_end)
218   {
219     for (size_t a = a_begin; a < a_end; ++a)
220     {
221       alloc_type & allocation = *(allocation_queue[a]);
222       const size_t size = allocation.size;
223       const unsigned char rankbyte = rank & 0xFF;
224
225       const auto ptr = allocation.ptr = (unsigned char*)malloc(size);
226       if (ptr == nullptr)
227       {
228         printf("Error: malloc() failure in rank %d, test %zu, allocation %zu\n", rank, testnum, a);
229         MPI_Abort(MPI_COMM_WORLD, 1);
230       }
231       ptr[0] = ptr[size-1] = rankbyte;
232
233 #ifdef MIGRATION_OVERKILL
234       ++eventnum;
235       if (eventnum == migrationinterval)
236       {
237         eventnum = 0;
238         request_migration();
239       }
240 #endif
241     }
242   };
243
244   auto free_loop = [&](const size_t a_begin, const size_t a_end)
245   {
246     for (size_t a = a_begin; a < a_end; ++a)
247     {
248       alloc_type & allocation = *(allocation_queue[a]);
249       const size_t size = allocation.size;
250       const unsigned char rankbyte = rank & 0xFF;
251
252       const auto ptr = allocation.ptr;
253       if (ptr[0] != rankbyte || ptr[size-1] != rankbyte)
254       {
255         printf("Error: Correctness failure in rank %d, test %zu, allocation %zu\n", rank, testnum, a);
256         MPI_Abort(MPI_COMM_WORLD, 2);
257       }
258       free(ptr);
259       allocation.ptr = nullptr;
260
261 #ifdef MIGRATION_OVERKILL
262       ++eventnum;
263       if (eventnum == migrationinterval)
264       {
265         eventnum = 0;
266         request_migration();
267       }
268 #endif
269     }
270   };
271
272   auto undetermined_loop = [&](const size_t a_begin, const size_t a_end)
273   {
274     for (size_t a = a_begin; a < a_end; ++a)
275     {
276       alloc_type & allocation = *(allocation_queue[a]);
277       const size_t size = allocation.size;
278       const unsigned char rankbyte = rank & 0xFF;
279
280       auto ptr = allocation.ptr;
281       if (ptr == nullptr)
282       {
283         ptr = allocation.ptr = (unsigned char*)malloc(size);
284         if (ptr == nullptr)
285         {
286           printf("Error: malloc() failure in rank %d, test %zu, allocation %zu\n", rank, testnum, a);
287           MPI_Abort(MPI_COMM_WORLD, 1);
288         }
289         ptr[0] = ptr[size-1] = rankbyte;
290       }
291       else
292       {
293         if (ptr[0] != rankbyte || ptr[size-1] != rankbyte)
294         {
295           printf("Error: Correctness failure in rank %d, test %zu, allocation %zu\n", rank, testnum, a);
296           MPI_Abort(MPI_COMM_WORLD, 2);
297         }
298         allocation.ptr = nullptr;
299         free(ptr);
300       }
301
302 #ifdef MIGRATION_OVERKILL
303       ++eventnum;
304       if (eventnum == migrationinterval)
305       {
306         eventnum = 0;
307         request_migration();
308       }
309 #endif
310     }
311   };
312
313   auto reset_queue = [&]()
314   {
315     alloc_type ** q = allocation_queue;
316     for (alloc_type * al = allocations, * al_end = al + numallocs; al < al_end; ++al)
317       *(q++) = al;
318   };
319
320   // tests freeing after every segment
321   auto test_by_segment = [&](std::function<void(size_t)> between = [](size_t){}, std::function<void(size_t)> after = [](size_t){})
322   {
323 #ifdef MIGRATION_OVERKILL
324     eventnum = 0;
325 #endif
326
327     if (testnum == maxtests)
328     {
329       printf("Error: Increase maxtests.\n");
330       MPI_Abort(MPI_COMM_WORLD, 10);
331     }
332
333     unsigned long long test_duration_count = 0;
334
335     MPI_Barrier(MPI_COMM_WORLD);
336
337     for (size_t s = 1; s < numsegments; ++s)
338     {
339       const time_point t_0 = clock_type::now();
340       alloc_loop(segments[s-1], segments[s]);
341       const time_point t_1 = clock_type::now();
342
343       request_migration();
344       between(s);
345
346       const time_point t_2 = clock_type::now();
347       free_loop(segments[s-1], segments[s]);
348       const time_point t_3 = clock_type::now();
349
350       request_migration();
351       after(s);
352
353       const duration_type test_duration = (t_3 - t_2) + (t_1 - t_0);
354       test_duration_count += test_duration.count();
355     }
356
357     unsigned long long duration_count = 0;
358     MPI_Reduce(&test_duration_count, &duration_count, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX, 0, MPI_COMM_WORLD);
359     tests[testnum].duration_count = duration_count;
360
361     ++testnum;
362   };
363
364   // tests freeing at the end
365   auto test_all = [&](std::function<void()> between = [](){}, std::function<void()> after = [](){})
366   {
367 #ifdef MIGRATION_OVERKILL
368     eventnum = 0;
369 #endif
370
371     if (testnum == maxtests)
372     {
373       printf("Error: Increase maxtests.\n");
374       MPI_Abort(MPI_COMM_WORLD, 10);
375     }
376
377     MPI_Barrier(MPI_COMM_WORLD);
378
379     const time_point t_0 = clock_type::now();
380     alloc_loop(0, numallocs);
381     const time_point t_1 = clock_type::now();
382
383     request_migration();
384     between();
385
386     const time_point t_2 = clock_type::now();
387     free_loop(0, numallocs);
388     const time_point t_3 = clock_type::now();
389
390     request_migration();
391     after();
392
393     const duration_type test_duration = (t_3 - t_2) + (t_1 - t_0);
394     unsigned long long test_duration_count = test_duration.count();
395
396     unsigned long long duration_count = 0;
397     MPI_Reduce(&test_duration_count, &duration_count, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX, 0, MPI_COMM_WORLD);
398     tests[testnum].duration_count = duration_count;
399
400     ++testnum;
401   };
402
403   // tests with alloc and free interspersed
404   auto test_mixed = [&]()
405   {
406 #ifdef MIGRATION_OVERKILL
407     eventnum = 0;
408 #endif
409
410     if (testnum == maxtests)
411     {
412       printf("Error: Increase maxtests.\n");
413       MPI_Abort(MPI_COMM_WORLD, 10);
414     }
415
416     MPI_Barrier(MPI_COMM_WORLD);
417
418     const time_point t_0 = clock_type::now();
419     undetermined_loop(0, numallocs*2);
420     const time_point t_1 = clock_type::now();
421
422     request_migration();
423
424     const duration_type test_duration = t_1 - t_0;
425     unsigned long long test_duration_count = test_duration.count();
426
427     unsigned long long duration_count = 0;
428     MPI_Reduce(&test_duration_count, &duration_count, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX, 0, MPI_COMM_WORLD);
429     tests[testnum].duration_count = duration_count;
430
431     ++testnum;
432   };
433
434   auto shuffle_segment = [&](size_t s)
435   {
436     std::shuffle(allocation_queue + segments[s-1], allocation_queue + segments[s], generator);
437   };
438   auto shuffle_segments = [&]()
439   {
440     for (size_t s = 1; s < numsegments; ++s)
441       shuffle_segment(s);
442   };
443   auto shuffle_all = [&]()
444   {
445     std::shuffle(allocation_queue, allocation_queue + numallocs, generator);
446   };
447
448   auto reverse_segment = [&](size_t s)
449   {
450     std::reverse(allocation_queue + segments[s-1], allocation_queue + segments[s]);
451   };
452   auto reverse_segments = [&]()
453   {
454     for (size_t s = 1; s < numsegments; ++s)
455       reverse_segment(s);
456   };
457   auto reverse_all = [&]()
458   {
459     std::reverse(allocation_queue, allocation_queue + numallocs);
460   };
461
462   auto shuffle_segments_and_reverse_all = [&]()
463   {
464     shuffle_segments();
465     reverse_all();
466   };
467
468   auto tests_static = [&](const char *desc1)
469   {
470     // allocate and free in the original order
471
472     tests[testnum].description1 = desc1;
473     tests[testnum].description2 = "FIFO free, batched by segment";
474     test_by_segment();
475
476     tests[testnum].description1 = desc1;
477     tests[testnum].description2 = "FIFO free, one batch";
478     test_all();
479
480
481     // allocate in the original order, free in the reverse order
482
483     tests[testnum].description1 = desc1;
484     tests[testnum].description2 = "LIFO free, batched by segment";
485     test_by_segment(reverse_segment, reverse_segment);
486
487     tests[testnum].description1 = desc1;
488     tests[testnum].description2 = "LIFO free within segments, one batch";
489     test_all(reverse_segments, reverse_segments);
490
491     tests[testnum].description1 = desc1;
492     tests[testnum].description2 = "LIFO free overall, one batch";
493     test_all(reverse_all, reverse_all);
494   };
495
496   auto tests_dynamic = [&](const char *desc1)
497   {
498     tests[testnum].description1 = desc1;
499     tests[testnum].description2 = "within segments, batched by segment";
500     test_by_segment(shuffle_segment);
501
502     tests[testnum].description1 = desc1;
503     tests[testnum].description2 = "within segments, FIFO segment order, one batch";
504     test_all(shuffle_segments);
505
506     tests[testnum].description1 = desc1;
507     tests[testnum].description2 = "within segments, LIFO segment order, one batch";
508     test_all(shuffle_segments_and_reverse_all); // reverse the segment order
509
510     tests[testnum].description1 = desc1;
511     tests[testnum].description2 = "overall, one batch";
512     test_all(shuffle_all);
513   };
514
515   auto tests_mixed = [&](const char *desc1)
516   {
517     {
518       alloc_type ** q = allocation_queue;
519       for (size_t s = 1; s < numsegments; ++s)
520       {
521         const size_t a_begin = segments[s-1], a_end = segments[s];
522
523         alloc_type ** const q_begin = q;
524
525         alloc_type * const al_begin = allocations + a_begin, * const al_end = allocations + a_end;
526         for (alloc_type * al = al_begin; al < al_end; ++al)
527           *(q++) = al;
528         for (alloc_type * al = al_begin; al < al_end; ++al)
529           *(q++) = al;
530
531         std::shuffle(q_begin, q, generator);
532       }
533     }
534     tests[testnum].description1 = desc1;
535     tests[testnum].description2 = "within segments, batched by segment";
536     test_mixed();
537
538     {
539       alloc_type ** q = allocation_queue;
540       for (alloc_type * al = allocations, * al_end = al + numallocs; al < al_end; ++al)
541         *(q++) = al;
542       for (alloc_type * al = allocations, * al_end = al + numallocs; al < al_end; ++al)
543         *(q++) = al;
544     }
545     std::shuffle(allocation_queue, allocation_queue + queuesize, generator);
546     tests[testnum].description1 = desc1;
547     tests[testnum].description2 = "overall, one batch";
548     test_mixed();
549   };
550
551
552   MPI_Barrier(MPI_COMM_WORLD);
553   const time_point t_0 = clock_type::now();
554
555   reset_queue();
556
557   tests_static("distinct phases, without shuffling, ");
558
559   shuffle_segments();
560   tests_static("distinct phases, static shuffle within segments, ");
561
562   shuffle_all();
563   tests_static("distinct phases, static shuffle overall, ");
564
565   shuffle_all();
566   tests_dynamic("distinct phases, shuffling between phases ");
567
568   tests_mixed("one phase, shuffled ");
569
570   MPI_Barrier(MPI_COMM_WORLD);
571   const time_point t_1 = clock_type::now();
572
573
574   const duration_type overall_duration = t_1 - t_0;
575   unsigned long long overall_duration_count = overall_duration.count();
576
577   // print results
578   if (rank == 0)
579   {
580     unsigned long long total_duration_count = 0;
581
582     printf("malloc stress test results:\n");
583     printf("   # - duration (ns) - description\n");
584     for (size_t t = 0; t < testnum; ++t)
585     {
586       const test_type & test = tests[t];
587
588       total_duration_count += test.duration_count;
589
590       printf("%4zu - %13llu - %s%s\n", t+1, test.duration_count, test.description1, test.description2);
591     }
592     printf(" all - %13llu - total\n", total_duration_count);
593
594     struct rusage usage;
595     getrusage(RUSAGE_SELF, &usage);
596
597     printf("memory usage high water mark ("
598 #ifdef __APPLE__
599       "bytes"
600 #else
601       "kilobytes"
602 #endif
603       "): %lu\n", usage.ru_maxrss);
604     printf("overall test duration (ns) including migration, shuffling, barriers, etc: %llu\n", overall_duration_count);
605   }
606 }
607
608 int main(int argc, char** argv)
609 {
610   MPI_Init(&argc, &argv);
611
612   int rank;
613   int p;
614   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
615   MPI_Comm_size(MPI_COMM_WORLD, &p);
616
617   uint32_t randomseed;
618
619   if (argc > 1)
620   {
621     randomseed = (uint32_t)atol(argv[1]);
622   }
623   else
624   {
625     if (rank == 0)
626       randomseed = std::chrono::system_clock::now().time_since_epoch().count();
627
628     MPI_Bcast(&randomseed, 1, MPI_UINT32_T, 0, MPI_COMM_WORLD);
629   }
630
631   if (rank == 0)
632     printf("memory test: ./" isomalloc_method_str " (...) +vp%i %" PRIu32 "\n", p, randomseed);
633
634   malloc_stress(rank, p, randomseed);
635
636   MPI_Finalize();
637
638   return 0;
639 }