source: benchmark/rmit.py@ 5465377c

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 5465377c was 836c9925, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Minor fixes to rmit in case keys differ

  • Property mode set to 100755
File size: 6.7 KB
RevLine 
[7a2a3af]1#!/usr/bin/python3
2"""
3Python Script to implement R.M.I.T. testing : Randomized Multiple Interleaved Trials
4
5./rmit.py run COMMAND CANDIDATES
6-t trials
7-o option:values
8"""
9
10
11import argparse
[dbb1073]12import datetime
[7a2a3af]13import itertools
14import os
15import random
16import re
17import subprocess
18import sys
19
20
21def parse_range(x):
22 result = []
23 for part in x.split(','):
24 if '-' in part:
25 a, b = part.split('-')
26 a, b = int(a), int(b)
27 result.extend(range(a, b + 1))
28 else:
29 a = int(part)
30 result.append(a)
31 return result
32
33class DependentOpt:
34 def __init__(self, key, value):
35 self.key = key
36 self.value = value
37 self.vars = re.findall("[a-zA-Z]", value)
38
39def parse_option(opt):
40 match = re.search("^(.*):(.*)$", opt)
41 if not match :
42 print('ERROR: extra options should match pattern .*:.*, got {}'.format(opt), file=sys.stderr)
43 sys.exit(1)
44
45 key = match.group(1)
46 values = match.group(2)
47
48 try:
49 num = int(values)
50 return key, [num]
51 except:
52 pass
53
54 if re.search("^[0-9-,]+$", values):
55 values = parse_range(values)
56 return key, [v for v in values]
57 else:
58 return key, DependentOpt(key, values)
59
60def eval_one(fmt, vals):
61 orig = fmt
62 for k, v in vals:
63 fmt = fmt.replace(k, str(v))
64
65 if not re.search("^[0-9-/*+ ]+$", fmt):
66 print('ERROR: pattern option {} (interpreted as {}) could not be evaluated'.format(orig, fmt), file=sys.stderr)
67 sys.exit(1)
68
69 return eval(fmt)
70
71def eval_options(opts):
72 dependents = [d for d in opts.values() if type(d) is DependentOpt]
73 processed = []
74 nopts = []
75 for d in dependents:
76 processed.append(d.key)
77 lists = []
78 for dvar in d.vars:
79 if not dvar in opts.keys():
80 print('ERROR: extra pattern option {}:{} uses unknown key {}'.format(d.key,d.value,dvar), file=sys.stderr)
81 sys.exit(1)
82
83 lists.append([(dvar, o) for o in opts[dvar]])
84 processed.append(dvar)
85
86 kopt = []
87 for vals in list(itertools.product(*lists)):
88 res = ['-{}'.format(d.key), "{}".format(eval_one(d.value, vals))]
89 for k, v in vals:
90 res.extend(['-{}'.format(k), "{}".format(v)])
91 kopt.append(res)
92 nopts.append(kopt)
93
94
95 for k, vals in opts.items():
96 if k not in processed:
97 kopt = []
98 for v in vals:
99 kopt.append(['-{}'.format(k), "{}".format(v)])
100 nopts.append(kopt)
101
102 return nopts
103
[dbb1073]104def actions_eta(actions):
105 time = 0
106 for a in actions:
107 i = 0
108 while i < len(a):
109 if a[i] == '-d':
110 i += 1
111 if i != len(a):
112 time += int(a[i])
113 i += 1
114 return time
115
[7a2a3af]116if __name__ == "__main__":
117 # ================================================================================
118 # parse command line arguments
119 formats = ['raw', 'csv']
120 parser = argparse.ArgumentParser(description='Python Script to implement R.M.I.T. testing : Randomized Multiple Interleaved Trials')
121 parser.add_argument('--list', help='List all the commands that would be run', action='store_true')
122 parser.add_argument('--format', help='How to print the result', choices=formats, default='csv')
123 parser.add_argument('--file', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
124 parser.add_argument('-t', '--trials', help='Number of trials to run per combinaison', type=int, default=3)
125 parser.add_argument('-o','--option',action='append')
126 parser.add_argument('command', metavar='command', type=str, nargs=1, help='the command prefix to run')
127 parser.add_argument('candidates', metavar='candidates', type=str, nargs='*', help='the candidate suffix to run')
128
129 try:
130 options = parser.parse_args()
131 except:
132 print('ERROR: invalid arguments', file=sys.stderr)
133 parser.print_help(sys.stderr)
134 sys.exit(1)
135
136 # ================================================================================
137 # Identify the commands to run
138 commands = ["./" + options.command[0] + "-" + c for c in options.candidates]
139 for c in commands:
140 if not os.path.isfile(c):
141 print('ERROR: invalid command {}, file does not exist'.format(c), file=sys.stderr)
142 sys.exit(1)
143
144 if not os.access(c, os.X_OK):
145 print('ERROR: invalid command {}, file not executable'.format(c), file=sys.stderr)
146 sys.exit(1)
147
148
149 # ================================================================================
150 # Identify the options to run
151 opts = dict([parse_option(o) for o in options.option])
152
153 # Evaluate the options (options can depend on the value of other options)
154 opts = eval_options(opts)
155
156 # ================================================================================
157 # Figure out all the combinations to run
158 actions = []
159 for p in itertools.product(range(options.trials), commands, *opts):
160 act = [p[1]]
161 for o in p[2:]:
162 act.extend(o)
163 actions.append(act)
164
165 # ================================================================================
166 # Figure out all the combinations to run
167 if options.list:
168 for a in actions:
169 print(" ".join(a))
170 sys.exit(0)
171
172
173 # ================================================================================
174 # Prepare to run
175
[dbb1073]176 # find expected time
177 time = actions_eta(actions)
178 print("Running {} trials{}".format(len(actions), "" if time == 0 else " (expecting to take {}".format(str(datetime.timedelta(seconds=int(time)))) ))
179
180 random.shuffle(actions)
[7a2a3af]181 result = []
182
183 # ================================================================================
184 # Run
185 for i, a in enumerate(actions):
186 sa = " ".join(a)
187 print("{}/{} : {} \r".format(i, len(actions), sa), end = '')
188 fields = {}
189 with subprocess.Popen( a, stdout = subprocess.PIPE, stderr = subprocess.PIPE) as proc:
190 out, err = proc.communicate()
191 if proc.returncode != 0:
192 print("ERROR: command '{}' encountered error, returned code {}".format(sa, proc.returncode), file=sys.stderr)
193 print(err.decode("utf-8"))
194 sys.exit(1)
195 for s in out.decode("utf-8").splitlines():
196 match = re.search("^(.*):(.*)$", s)
197 if match:
198 fields[match.group(1).strip()] = float(match.group(2).strip().replace(',',''))
199
200 result.append([a[0][2:], sa, fields])
201
202 print("Done ")
203
204 # ================================================================================
205 # Print csv
206 if options.format == 'raw':
207 for r in result:
208 print(r, file=options.file)
209 sys.exit(0)
210
211 # ================================================================================
212 # Print csv
213 if options.format == 'csv':
214 # Clean result
215 headers = ["series", "command"]
216 data = []
217 first = True
218 for r in result:
219 if first:
220 first = False
221 headers.extend(r[2].keys())
222 else :
223 pass
224
225 d = [r[0], r[1]]
226 for k in headers[2:]:
[836c9925]227 try:
228 d.append(r[2][k])
229 except:
230 d.append(0.0)
[7a2a3af]231
232 data.append(d)
233
234 # Print csv
235 print(",\t".join(headers), file=options.file)
236 for d in data:
237 print(",\t".join(["{}".format(dd) for dd in d]), file=options.file)
238 sys.exit(0)
Note: See TracBrowser for help on using the repository browser.