source: doc/theses/mike_brooks_MMath/benchmarks/list/driver.c@ 5ba1356

Last change on this file since 5ba1356 was 2b0e754, checked in by Michael Brooks <mlbrooks@…>, 8 weeks ago

Continue disabling harness features, achieving best-case times that match Peter's, on the three tests with new CSVs here.

The fully-disabled harness probably still fools the optimizer because it uses the Buhr-Dice "pass function" trick in place of the disabled observation and iterators array. That these times are now often beating Peter's requires further investigation.

Make STL run with (cpp-sltref) and without (cpp-stlrefAlloGlib) llheap.
Include peter-*.csv from runs on Swift. (Thesis still builds with original numbers from labpc.)
Add data post-processing for sorting and aggregation, leveraging thesis's plots' framework.

Add makefile-saved setups for matching Peter.
Add ability to disable "observation" (use of volatiles) and iterators array (support for remelem).
Add integrated clean-build-run targets for varying the "disable" switches.
Strengthen disable-interleaving mode to avoid the extra loops on remove.

Still to entertain some of this stripping being unnecessary for achieving near Peter-match.
Still to compare costs of the relevant stripped features, and recommend harness variation(s) to for use in thesis.

  • Property mode set to 100644
File size: 16.5 KB
Line 
1#include <time.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#ifdef DISABLE_OBSERVATION
7#include "proglang.h"
8#define bobs_init(...)
9#else
10#include "observation.h"
11#endif
12
13#ifdef TINY_USER_ITEMS
14 #define UDATA_T char
15 #define UDATA_LEN 1
16 #define UDATA_USE_POS 0
17#else
18 #define UDATA_T int
19 #define UDATA_LEN 64
20 #define UDATA_USE_POS 17
21#endif
22
23typedef struct B_UserItem
24 BFX_EXTRUSION_DECL(B_UserItem)
25{
26 BFX_INTRUSION(B_UserItem)
27// BFX_LISTED_ELEM_T(B_UserItem) selfListed;
28 UDATA_T userdata[ UDATA_LEN ];
29}
30B_UserItem;
31
32BFX_EXTRUSION_FOLLOWUP(B_UserItem)
33
34#if defined(NDEBUG) || (defined(__cforall) && !defined(__CFA_DEBUG__))
35 enum { DefaultNumNodes = 1000, DefaultExperimentDurSec = 1, DefaultCheckDonePeriod = 1000, DefaultExperimentDurOpCount = -1, DefaultSeed = 5 };
36 const double DefaultInterleaveFrac = 0.0;
37 #define TRACE(tp)
38#else
39 enum { DefaultNumNodes = 10, DefaultExperimentDurSec = 1, DefaultCheckDonePeriod = 2, DefaultExperimentDurOpCount = 20, DefaultSeed = 5 };
40 const double DefaultInterleaveFrac = 0.5;
41 static const char * tp_filter
42 // = "";
43 // = "+ea";
44 = "*";
45 #define TRACE(tp) \
46 if (strcmp("*", tp_filter) == 0 || strchr(tp_filter, tp)) { \
47 printf("%c", tp); \
48 bobs_report(); \
49 }
50#endif
51
52static B_UserItem *ui = NULL;
53
54static BFX_LISTED_ELEM_T(B_UserItem) *listedItems = NULL;
55static BFX_LISTED_ELEM_T(B_UserItem) observedItem;
56
57static BFX_LIST_HEAD_T(B_UserItem) lst;
58
59#ifdef DISABLE_OBSERVATION
60MAYBE_EXTERN_C (
61 void bobs_seek(unsigned int i) {}
62 void bobs_moveNext() {}
63 void bobs_movePrev() {}
64 int bobs_hasCurrent() { return 0; }
65 void * bobs_getCurrentLoc() { return NULL; }
66 int bobs_getCurrentVal() { return 0; }
67 // enum bobs_op_movement_t bobs_op_movement = OP_MOVEMENT;
68 // enum bobs_op_polarity_t bobs_op_polarity = OP_POLARITY;
69)
70
71#else
72
73MAYBE_EXTERN_C (
74
75 volatile size_t bobs_ops_completed = 0;
76 volatile unsigned int bobs_prog_inserting = 0;
77 volatile unsigned int bobs_prog_removing = 0;
78 volatile unsigned int bobs_prog_removing_end = 0;
79 volatile unsigned int bobs_prog_rollover_flag = 0;
80 // bobs_prog_rem_pos (defined after BOP_REMPROGEND_IS_REMNO_BASED)
81
82 void bobs_seek(unsigned int i) {
83 observedItem = listedItems[i];
84 }
85
86 void bobs_moveNext() {
87 observedItem = BFX_GET_AFTER(B_UserItem, lst, observedItem);
88 }
89
90 void bobs_movePrev() {
91 observedItem = BFX_GET_BEFORE(B_UserItem, lst, observedItem);
92 }
93
94 int bobs_hasCurrent() {
95 return BFX_IS_VALID_POS(B_UserItem, lst, observedItem);
96 }
97
98 void * bobs_getCurrentLoc() {
99 return BFX_DEREF_POS(B_UserItem, lst, observedItem);
100 }
101 int bobs_getCurrentVal() {
102 B_UserItem * curUI = BFX_DEREF_POS(B_UserItem, lst, observedItem);
103 return curUI->userdata[ UDATA_USE_POS ];
104 }
105
106 enum bobs_op_movement_t bobs_op_movement = OP_MOVEMENT;
107 enum bobs_op_polarity_t bobs_op_polarity = OP_POLARITY;
108)
109#endif
110
111
112#ifndef DISABLE_OBSERVATION
113
114// Remove progress end (number) is based (upon) remove-number
115// True when an OP's REMELEM used remNo to choose which element to remove
116// False otherwise; notably including when REMELEM just bases upon first/last
117// Default to false.
118#ifndef BOP_REMPROGEND_IS_REMNO_BASED
119#define BOP_REMPROGEND_IS_REMNO_BASED false
120#endif
121MAYBE_EXTERN_C (
122 volatile unsigned int const * bobs_prog_rem_pos
123 = BOP_REMPROGEND_IS_REMNO_BASED ? & bobs_prog_removing_end : & bobs_prog_removing;
124)
125
126#endif // ndef DISABLE_OBSERVATION
127
128unsigned int uDefaultPreemption() {
129 return 0;
130}
131
132#ifdef DISABLE_ITERS_AR
133// Saves on memory accesses, makes element-oriented removals and observation impossible (instead, they crash)
134static inline BFX_LISTED_ELEM_T(B_UserItem) buhrdice_pass( BFX_LISTED_ELEM_T(B_UserItem) v ) { // prevent eliding, cheaper than volatile
135 __asm__ __volatile__ ( "" : "+r"(v) );
136 return v ;
137} // pass
138#define ITERS_SAVE(i, insertElemExpr) buhrdice_pass(insertElemExpr)
139#endif
140
141int main(int argc, const char *argv[]) {
142
143 #ifdef DISABLE_OBSERVATION
144 // define the outbound dependencies as locals, for compiling into nops
145 size_t bobs_ops_completed = 0;
146 unsigned int bobs_prog_inserting = 0;
147 unsigned int bobs_prog_removing = 0;
148 unsigned int bobs_prog_removing_end = 0;
149 unsigned int bobs_prog_rollover_flag = 0;
150 #endif
151
152 const char * usage_args = "[ExperimentDurSec [CheckDonePeriod [NumNodes [ExperimentDurOpCount [Seed [InterleaveFrac]]]]]]";
153 const int static_arg_posns = 6;
154
155 unsigned int ExperimentDurSec = DefaultExperimentDurSec;
156 unsigned int CheckDonePeriod = DefaultCheckDonePeriod;
157 unsigned int NumNodes = DefaultNumNodes;
158 size_t ExperimentDurOpCount = DefaultExperimentDurOpCount;
159 unsigned int Seed = DefaultSeed;
160 double InterleaveFrac = DefaultInterleaveFrac;
161
162 switch (((argc - 1) < static_arg_posns) ? (argc - 1) : static_arg_posns) {
163 case 6: InterleaveFrac = atof(argv[6]);
164 case 5: Seed = atoi(argv[5]);
165 case 4: ExperimentDurOpCount = atol(argv[4]);
166 case 3: NumNodes = atoi(argv[3]);
167 case 2: CheckDonePeriod = atoi(argv[2]);
168 case 1: ExperimentDurSec = atoi(argv[1]);
169 }
170
171 // printf("ExperimentDurSec=%d, CheckDonePeriod=%d, NumNodes=%d, ExperimentDurOpCount=%zd, Seed=%d,\n",
172 // ExperimentDurSec, CheckDonePeriod, NumNodes, ExperimentDurOpCount, Seed );
173
174 if (ExperimentDurSec == 0 || CheckDonePeriod == 0 || NumNodes == 0 || ExperimentDurOpCount == 0 || Seed == 0 ) {
175 printf("usage: %s %s\n", argv[0], usage_args);
176 return -1;
177 }
178
179 #ifdef DISABLE_CLOCK_RECHECK
180 if (ExperimentDurSec != -1) {
181 printf("Error: experiment compiled as fixed-work only. ExperimentDurSec (currently %d) must be set to -1.\nUsage: %s %s\n", ExperimentDurSec, argv[0], usage_args);
182 return -1;
183 }
184 #endif
185
186 // Shuffling makes listed items' physical order in memory different from their order within to the list.
187 // Affects insertion: next item to insert picked through insertOrdShuf.
188 #ifdef DISABLE_SHUFFLING_INDIRECTION
189 #define INSERTPOS(insertNum) insertNum
190 #else
191 // To ensure random memory order of nodes being inserted, do so according to a shuffled ordering of them.
192 unsigned int * insertOrdShuf = (unsigned int *) malloc( (size_t)NumNodes * sizeof(unsigned int) );
193 if (!insertOrdShuf) {
194 printf("malloc request for %zd bytes for insertOrdShuf refused\n", (size_t)NumNodes * (size_t)sizeof(unsigned int));
195 return 1;
196 }
197 // Fill with the ordinals (iota)
198 for (int i = 0; i < NumNodes; i++) {
199 insertOrdShuf[i] = i;
200 }
201 // Dummy "Seed" of -1 means skip the shuffle: measure overhead of insertOrdShuf indirection
202 if (Seed != -1) {
203 // Shuffle
204 srand(Seed);
205 for (unsigned int i = 0; i < NumNodes; i++) {
206 unsigned int nodesRemaining = NumNodes - i;
207 unsigned int swapWith = i + rand() % nodesRemaining;
208 unsigned int tempValue = insertOrdShuf[swapWith];
209 insertOrdShuf[swapWith] = insertOrdShuf[i];
210 insertOrdShuf[i] = tempValue;
211 }
212 }
213 #define INSERTPOS(insertNum) insertOrdShuf[insertNum]
214 #endif
215
216 // Interleaving affects the list position where an element-oriented operation occurs: at an end vs. in the middle.
217 // Perterbs the sequence of logical insert/remove numbers presented to the OP cartridge, e.g. from [0 1 2 3 4 5 6]
218 // to [3 0 4 1 5 2 6], which is [mid end mid end mid end solo], for a perfect-alternation interleave; except that the
219 // end/mid interleave is atually selected randomly.
220 #ifdef DISABLE_INTERLEAVING
221 #define nextInterleave 0
222 #else
223 const unsigned int INTRL_KEYLEN = 64;
224 unsigned char interleaveKey[INTRL_KEYLEN];
225 unsigned char nextInterleavePos = 0;
226 {
227 unsigned int numOnes = INTRL_KEYLEN * InterleaveFrac;
228 unsigned int numZeros = INTRL_KEYLEN - numOnes;
229 // generate randomly drawn 0/1
230 memset( interleaveKey , 0, numZeros ); // zeros then ones
231 memset( interleaveKey+numZeros, 1, numOnes );
232 for (unsigned int i = 0; i < 64; i++) { // shuffle it
233 unsigned int nodesRemaining = 64 - i;
234 unsigned int swapWith = i + rand() % nodesRemaining;
235 unsigned char tempValue = interleaveKey[swapWith];
236 interleaveKey[swapWith] = interleaveKey[i];
237 interleaveKey[i] = tempValue;
238 }
239 #define nextInterleave (interleaveKey[nextInterleavePos = (nextInterleavePos + 1) % 64])
240 }
241 {
242 unsigned int z = 0, o = 0;
243 for ( int i = 0; i < INTRL_KEYLEN; i++ ) {
244 if (interleaveKey[i]) o++;
245 else z++;
246 }
247 // printf("Interleaving with %u in middle and %u at end\n", o, z);
248 }
249 // printf("interleave key begins %016llx\n", *(unsigned long long*)interleaveKey);
250 // printf("interleave key begins %016llx\n", *(unsigned long long*)(interleaveKey+8));
251 // printf("sample interleave value %d\n", nextInterleave);
252 // printf("sample interleave value %d\n", nextInterleave);
253 // printf("sample interleave value %d\n", nextInterleave);
254 // printf("sample interleave value %d\n", nextInterleave);
255 // printf("sample interleave value %d\n", nextInterleave);
256 // printf("sample interleave value %d\n", nextInterleave);
257 // printf("sample interleave value %d\n", nextInterleave);
258 // printf("sample interleave value %d\n", nextInterleave);
259 // printf("sample interleave value %d\n", nextInterleave);
260 // printf("sample interleave value %d\n", nextInterleave);
261 // printf("sample interleave value %d\n", nextInterleave);
262 // printf("sample interleave value %d\n", nextInterleave);
263 #endif
264
265 ui = (B_UserItem*) malloc( (size_t)NumNodes * (size_t)sizeof(B_UserItem) );
266 if (!ui) {
267 printf("malloc request for %zd bytes for ui refused\n", (size_t)NumNodes * (size_t)sizeof(B_UserItem));
268 return 1;
269 }
270 memset(ui, 0, (size_t)NumNodes * (size_t)sizeof(B_UserItem));
271
272 #ifndef DISABLE_ITERS_AR
273 listedItems = (BFX_LISTED_ELEM_T(B_UserItem)*)malloc( (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem)) );
274 if (!listedItems) {
275 printf("malloc request for %zd bytes for listedItems refused\n", (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem)));
276 return 1;
277 }
278 memset(listedItems, 0, (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem)));
279 #define ITERS_SAVE(i, insertElemExpr) listedItems[i] = (insertElemExpr)
280 #endif
281
282 // Construct and fill with demo data
283 for (unsigned int i = 0; i < NumNodes; i++) {
284 B_UserItem * curUI = & ui[INSERTPOS(i)];
285 #ifdef __cforall
286 (*curUI){};
287 #endif
288 curUI->userdata[ UDATA_USE_POS ] = i;
289 }
290
291 BFX_INIT(B_UserItem, lst);
292
293 bobs_init(NumNodes);
294
295 // BOP_ADDFOO(lst, iters, insNo, item)
296 // BOP_REMFOO(lst, iters, remNo)
297 // lst lvalue of the list head being added to / removed from
298 // iters array of ADD return values, in logical-insert order; on ADD, is valid at [0..insNo)
299 // insNo interleave-perterbed counter of the ADD calls (logical insert number)
300 // remNo interleave-perterbed counter of the REM calls (logical remove number)
301 // item lvalue of the item being added
302 // Logical insert number 0 and remove number n-1 are given with a distinguished hook.
303 // Logical insert numbers [1,n) and remove numbers [0,n-1) are pumped by the basic SUT hooks.
304 // This pattern lets BOP cartridges that measure element-level operations know statically when there is a reference element in the list.
305 // The driver owns the relationship between a logical insert number and the location of the `item` argument within `ui`. (Scattered for randomness.)
306 // The BOP cartridge owns the relationship between logical remove number and any choice of an item in iters. (Defines stack vs queue.)
307
308 // Default init/teardown is insert/remove
309 // Cartridges whose SUT insert/remove actions work on empty lists need not provide special-case ones.
310 #ifndef BOP_INIT
311 #define BOP_INIT(lst, iters, insNo, item) BOP_INSERT(lst, iters, insNo, item)
312 #endif
313 #ifndef BOP_TEARDOWN
314 #define BOP_TEARDOWN(lst, iters, remNo) BOP_REMOVE(lst, iters, remNo)
315 #endif
316
317 double elapsed_sec = 0;
318 clock_t start = clock();
319
320 const unsigned int numMiddleNodes = (NumNodes-1) * InterleaveFrac;
321 const unsigned int numEndNodes = NumNodes - numMiddleNodes - 1;
322
323 // printf("Running with %u in the middle and %u at end\n", numMiddleNodes, numEndNodes);
324
325 const unsigned int removeBase[] = {0, numEndNodes};
326 const unsigned int removeLimit[] = {numEndNodes, numMiddleNodes};
327
328 size_t privateOpsCompleted = 0;
329
330 while (elapsed_sec <= (double) ExperimentDurSec && privateOpsCompleted < ExperimentDurOpCount) {
331 for ( int t = 0; t < CheckDonePeriod; t += 1 ) {
332 TRACE('a') // insert special first
333 ITERS_SAVE( 0,
334 BOP_INIT(lst, listedItems, 0, ui[INSERTPOS(0)]) );
335 TRACE('b') // insert general
336 for ( int privateCurInsert = 1;
337 (bobs_prog_inserting = privateCurInsert, privateCurInsert < NumNodes);
338 privateCurInsert += 1
339 ) {
340 TRACE('-')
341 ITERS_SAVE( privateCurInsert,
342 BOP_INSERT( lst, listedItems, privateCurInsert, ui[INSERTPOS(privateCurInsert)] ) );
343 TRACE('+')
344 }
345 #ifdef DISABLE_INTERLEAVING
346 // interleaving off, simple removes
347 // (remove logic of 2b01f8eb0956)
348 TRACE('c')
349 for ( int privateCurRemove = 1;
350 (bobs_prog_removing = privateCurRemove, privateCurRemove < NumNodes);
351 privateCurRemove += 1
352 ) {
353 TRACE('-')
354 BOP_REMOVE( lst, listedItems, privateCurRemove-1 );
355 TRACE('+')
356 }
357 #else
358 // interleaving on, complex removes
359 TRACE('c') // remove general
360 int removeProgress[] = { 0, 0 };
361 for ( int flip = 0;
362 (bobs_prog_removing = removeProgress[0] + removeProgress[1] + 1,
363 bobs_prog_removing_end = removeProgress[0] + 1,
364 flip = nextInterleave,
365 removeProgress[0] < removeLimit[0] && removeProgress[1] < removeLimit[1] );
366 removeProgress[flip] += 1
367 ) {
368 TRACE('-')
369 BOP_REMOVE( lst, listedItems, removeBase[flip]+removeProgress[flip] );
370 TRACE('+')
371 }
372 TRACE('X') // remove imbalanced
373 // most work done under general; it stops when either flip-side's work finishes
374 // now drain any any stragglers so both flip-sides' work finishes
375 for ( int flip = 0; flip < 2; flip ++ ) {
376 for ( ; (bobs_prog_removing = removeProgress[0] + removeProgress[1] + 1,
377 bobs_prog_removing_end = removeProgress[0] + 1,
378 removeProgress[flip] < removeLimit[flip] )
379 ; removeProgress[flip] += 1
380 ) {
381 TRACE('-')
382 BOP_REMOVE( lst, listedItems, removeBase[flip]+removeProgress[flip] );
383 TRACE('+')
384 }
385 }
386 #endif // DISABLE_INTERLEAVING
387 TRACE('D') // remove special last
388 BOP_TEARDOWN(lst, listedItems, NumNodes-1);
389 TRACE('d')
390
391 privateOpsCompleted += NumNodes;
392
393 bobs_prog_rollover_flag = 1;
394 TRACE('e')
395 bobs_prog_inserting = 0;
396 bobs_prog_removing = 0;
397 bobs_prog_removing_end = 0;
398 bobs_ops_completed = privateOpsCompleted;
399 TRACE('f')
400 bobs_prog_rollover_flag = 0;
401 TRACE('g')
402 }
403 #ifndef DISABLE_CLOCK_RECHECK
404 clock_t end = clock();
405 elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC);
406 #endif
407 }
408 #ifdef DISABLE_CLOCK_RECHECK
409 {
410 clock_t end = clock();
411 elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC);
412 }
413 #endif
414
415 double mean_op_dur_ns = elapsed_sec / ((double)bobs_ops_completed) * 1000 * 1000 * 1000;
416 printf("%s,%zd,%f,%f\n", argv[0], bobs_ops_completed, elapsed_sec, mean_op_dur_ns);
417
418 free(ui);
419 free(listedItems);
420 #ifndef DISABLE_SHUFFLING_INDIRECTION
421 free(insertOrdShuf);
422 #endif
423}
Note: See TracBrowser for help on using the repository browser.