tlds
Transactional Operations for Linked Data Structures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
bmharness.hpp
Go to the documentation of this file.
1 /**
2  * Copyright (C) 2011
3  * University of Rochester Department of Computer Science
4  * and
5  * Lehigh University Department of Computer Science and Engineering
6  *
7  * License: Modified BSD
8  * Please see the file LICENSE.RSTM for licensing information
9  */
10 
11 #ifndef BMHARNESS_HPP__
12 #define BMHARNESS_HPP__
13 
14 #include <cstdlib>
15 #include <iostream>
16 #include <signal.h>
17 #include <pthread.h>
18 #include <api/api.hpp>
19 #include <common/platform.hpp>
20 #include <common/locks.hpp>
21 #include "bmconfig.hpp"
22 
23 using std::string;
24 using std::cout;
25 
27  bmname(""),
28  duration(1),
29  execute(0),
30  threads(1),
31  nops_after_tx(0),
32  elements(256),
33  lookpct(34),
34  inspct(66),
35  sets(1),
36  ops(1),
37  time(0),
38  running(true),
39  txcount(0)
40 {
41 }
42 
43 Config CFG TM_ALIGN(64);
44 
45 /**
46  * Print benchmark configuration output
47  */
48 void dump_csv()
49 {
50  // csv output
51  std::cout << "csv"
52  << ", ALG=" << GET_ALGNAME()
53  << ", B=" << CFG.bmname << ", R=" << CFG.lookpct
54  << ", d=" << CFG.duration << ", p=" << CFG.threads
55  << ", X=" << CFG.execute << ", m=" << CFG.elements
56  << ", S=" << CFG.sets << ", O=" << CFG.ops
57  << ", txns=" << CFG.txcount << ", time=" << CFG.time
58  << ", throughput="
59  << (1000000000LL * CFG.txcount) / (CFG.time)
60  << std::endl;
61 }
62 
63 /**
64  * Print usage
65  */
66 void usage()
67 {
68  std::cerr << "Usage: CounterBench -C <stm algorithm> [flags]\n";
69  std::cerr << " -d: number of seconds to time (default 1)\n";
70  std::cerr << " -X: execute fixed tx count, not for a duration\n";
71  std::cerr << " -p: number of threads (default 1)\n";
72  std::cerr << " -N: nops between transactions (default 0)\n";
73  std::cerr << " -R: % lookup txns (remainder split ins/rmv)\n";
74  std::cerr << " -m: range of keys in data set\n";
75  std::cerr << " -B: name of benchmark\n";
76  std::cerr << " -S: number of sets to build (default 1)\n";
77  std::cerr << " -O: operations per transaction (default 1)\n";
78  std::cerr << " -h: print help (this message)\n\n";
79 }
80 
81 /**
82  * Parse command line arguments
83  */
84 void
85 parseargs(int argc, char** argv)
86 {
87  // parse the command-line options
88  int opt;
89  while ((opt = getopt(argc, argv, "N:d:p:hX:B:m:R:S:O:")) != -1) {
90  switch(opt) {
91  case 'd': CFG.duration = strtol(optarg, NULL, 10); break;
92  case 'p': CFG.threads = strtol(optarg, NULL, 10); break;
93  case 'N': CFG.nops_after_tx = strtol(optarg, NULL, 10); break;
94  case 'X': CFG.execute = strtol(optarg, NULL, 10); break;
95  case 'B': CFG.bmname = std::string(optarg); break;
96  case 'm': CFG.elements = strtol(optarg, NULL, 10); break;
97  case 'S': CFG.sets = strtol(optarg, NULL, 10); break;
98  case 'O': CFG.ops = strtol(optarg, NULL, 10); break;
99  case 'R':
100  CFG.lookpct = strtol(optarg, NULL, 10);
101  CFG.inspct = (100 - CFG.lookpct)/2 + strtol(optarg, NULL, 10);
102  break;
103  case 'h':
104  usage();
105  }
106  }
107 }
108 
109 /**
110  * Run some nops between transactions, to simulate some time being spent on
111  * computation
112  */
113 void
115 {
116  if (CFG.nops_after_tx)
117  for (uint32_t i = 0; i < CFG.nops_after_tx; i++)
118  spin64();
119 }
120 
121 /*** Signal handler to end a test */
122 extern "C" void catch_SIGALRM(int) {
123  CFG.running = false;
124 }
125 
126 /**
127  * Support a few lightweight barriers
128  */
129 void
130 barrier(uint32_t which)
131 {
132  static volatile uint32_t barriers[16] = {0};
133  CFENCE;
134  fai32(&barriers[which]);
135  while (barriers[which] != CFG.threads) { }
136  CFENCE;
137 }
138 
139 /*** Run a timed or fixed-count experiment */
140 void
141 run(uintptr_t id)
142 {
143  // create a transactional context (repeat calls from thread 0 are OK)
144  THREAD_INIT();
145 
146  // wait until all threads created, then set alarm and read timer
147  barrier(0);
148  if (id == 0) {
149  if (!CFG.execute) {
150  signal(SIGALRM, catch_SIGALRM);
151  alarm(CFG.duration);
152  }
153  CFG.time = getElapsedTime();
154  }
155 
156  // wait until read of start timer finishes, then start transactios
157  barrier(1);
158 
159  uint32_t count = 0;
160  uint32_t seed = id; // not everyone needs a seed, but we have to support it
161  if (!CFG.execute) {
162  // run txns until alarm fires
163  while (CFG.running) {
164  bench_test(id, &seed);
165  ++count;
166  nontxnwork(); // some nontx work between txns?
167  }
168  }
169  else {
170  // run fixed number of txns
171  for (uint32_t e = 0; e < CFG.execute; e++) {
172  bench_test(id, &seed);
173  ++count;
174  nontxnwork(); // some nontx work between txns?
175  }
176  }
177 
178  // wait until all txns finish, then get time
179  barrier(2);
180  if (id == 0)
181  CFG.time = getElapsedTime() - CFG.time;
182 
183  // add this thread's count to an accumulator
184  faa32(&CFG.txcount, count);
185 }
186 
187 /**
188  * pthread wrapper for running the experiments
189  *
190  * NB: noinline prevents this from getting inlined into main (and prevents
191  * run from being inlined there as well. This eliminates an
192  * _ITM_initializeProcess ordering problem if there's a transaction
193  * lexically scoped inside of main.
194  */
195 NOINLINE
196 void*
197 run_wrapper(void* i)
198 {
199  run((uintptr_t)i);
200  THREAD_SHUTDOWN();
201  return NULL;
202 }
203 
204 /**
205  * Main routine: parse args, set up the TM system, prep the benchmark, run
206  * the experiments, verify results, print results, and shut down the system
207  */
208 int main(int argc, char** argv) {
209  parseargs(argc, argv);
210  bench_reparse();
211  SYS_INIT();
212  THREAD_INIT();
213  bench_init();
214 
215  void* args[256];
216  pthread_t tid[256];
217 
218  // set up configuration structs for the threads we'll create
219  pthread_attr_t attr;
220  pthread_attr_init(&attr);
221  pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
222  for (uint32_t i = 0; i < CFG.threads; i++)
223  args[i] = (void*)i;
224 
225  // actually create the threads
226  for (uint32_t j = 1; j < CFG.threads; j++)
227  pthread_create(&tid[j], &attr, &run_wrapper, args[j]);
228 
229  // all of the other threads should be queued up, waiting to run the
230  // benchmark, but they can't until this thread starts the benchmark
231  // too...
232  run_wrapper(args[0]);
233 
234  // Don't call any more transactional functions, because run_wrapper called
235  // shutdown.
236 
237  // everyone should be done. Join all threads so we don't leave anything
238  // hanging around
239  for (uint32_t k = 1; k < CFG.threads; k++)
240  pthread_join(tid[k], NULL);
241 
242  bool v = bench_verify();
243  std::cout << "Verification: " << (v ? "Passed" : "Failed") << "\n";
244 
245  dump_csv();
246 
247  // And call sys shutdown stuff
248  SYS_SHUTDOWN();
249  return 0;
250 }
251 
252 #endif // BMHARNESS_HPP__
void spin64()
Definition: locks.hpp:36
void nontxnwork()
Definition: bmharness.hpp:114
bool set_op ops[]
Definition: stmskip.cc:238
#define NOINLINE
Definition: platform.hpp:48
Config()
Definition: bmharness.cpp:26
TxThread * threads[MAX_THREADS]
Definition: txthread.cpp:56
void usage()
Definition: bmharness.hpp:66
bool bench_verify()
Definition: CounterBench.cpp:74
#define SYS_SHUTDOWN()
Definition: common.hpp:94
Definition: normal.c:100
void parseargs(int argc, char **argv)
Definition: bmharness.hpp:85
void bench_init()
Definition: CounterBench.cpp:57
void barrier(uint32_t which)
Definition: bmharness.hpp:130
static int seed
Definition: mesh.cpp:40
#define THREAD_SHUTDOWN()
Definition: common.hpp:93
int main(int argc, char **argv)
Definition: bmharness.hpp:208
void bench_test(uintptr_t, uint32_t *)
Definition: CounterBench.cpp:64
#define SYS_INIT()
Definition: common.hpp:91
Definition: bmconfig.hpp:21
void bench_reparse()
Definition: CounterBench.cpp:89
void catch_SIGALRM(int)
Definition: bmharness.hpp:122
#define THREAD_INIT()
Definition: common.hpp:92
NOINLINE void * run_wrapper(void *i)
Definition: bmharness.hpp:197
void run(uintptr_t id)
Definition: bmharness.hpp:141
volatile unsigned long count
Definition: queues.cpp:53
void dump_csv()
Definition: bmharness.hpp:48
Config CFG TM_ALIGN(64)