diff options
Diffstat (limited to 'run_exps.py')
-rwxr-xr-x[-rw-r--r--] | run_exps.py | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/run_exps.py b/run_exps.py index e69de29..c589f51 100644..100755 --- a/run_exps.py +++ b/run_exps.py | |||
@@ -0,0 +1,192 @@ | |||
1 | #!/usr/bin/env python | ||
2 | from __future__ import print_function | ||
3 | |||
4 | import config.config as conf | ||
5 | import experiment.litmus_util as lu | ||
6 | import os | ||
7 | import re | ||
8 | |||
9 | from collections import defaultdict | ||
10 | from optparse import OptionParser | ||
11 | from experiment.executable.executable import Executable | ||
12 | from experiment.experiment import Experiment | ||
13 | from experiment.proc_entry import ProcEntry | ||
14 | |||
15 | |||
16 | def parse_args(): | ||
17 | parser = OptionParser(); | ||
18 | |||
19 | parser.add_option('-s', '--scheduler', dest='scheduler', | ||
20 | help='scheduler for all experiments') | ||
21 | parser.add_option('-d', '--duration', dest='duration', type='int', | ||
22 | help='duration (seconds) of tasks') | ||
23 | parser.add_option('-o', '--out-dir', dest='out_dir', | ||
24 | help='directory for data output', default=os.getcwd()) | ||
25 | parser.add_option('-p', '--params', dest='param_file', | ||
26 | help='file with experiment parameters') | ||
27 | parser.add_option('-f', '--schedule-file', dest='sched_file', | ||
28 | help='name of schedule files', | ||
29 | default=conf.DEFAULTS['sched_file']) | ||
30 | |||
31 | return parser.parse_args() | ||
32 | |||
33 | |||
34 | def convert_data(data): | ||
35 | """Convert a non-python schedule file into the python format""" | ||
36 | regex = re.compile( | ||
37 | |||
38 | r"(?P<PROC>^" | ||
39 | r"(?P<HEADER>/proc/\w+?/)?" | ||
40 | r"(?P<ENTRY>[\w\/]+)" | ||
41 | r"\s*{\s*(?P<CONTENT>.*?)\s*?}$)|" | ||
42 | r"(?P<SPIN>^(?P<TYPE>\w+?spin)?\s*?" | ||
43 | r"(?P<ARGS>\w[\s\w]*?)?\s*?$)", | ||
44 | re.S|re.I|re.M) | ||
45 | |||
46 | procs = [] | ||
47 | spins = [] | ||
48 | |||
49 | for match in regex.finditer(data): | ||
50 | if match.group("PROC"): | ||
51 | header = match.group("HEADER") or "/proc/litmus/" | ||
52 | loc = "{}{}".format(header, match.group("ENTRY")) | ||
53 | proc = (loc, match.group("CONTENT")) | ||
54 | procs.append(proc) | ||
55 | else: | ||
56 | prog = match.group("TYPE") or "rtspin" | ||
57 | spin = (prog, match.group("ARGS")) | ||
58 | spins.append(spin) | ||
59 | |||
60 | return {'proc' : procs, 'spin' : spins} | ||
61 | |||
62 | |||
63 | def get_dirs(sched_file, out_base_dir): | ||
64 | sched_leaf_dir = re.findall(r".*/([\w_-]+)/.*?$", sched_file)[0] | ||
65 | sched_full_dir = os.path.split(sched_file)[0] | ||
66 | |||
67 | work_dir = "%s/tmp" % sched_full_dir | ||
68 | |||
69 | if sched_full_dir == out_base_dir: | ||
70 | out_dir = "%s/data" % sched_full_dir | ||
71 | else: | ||
72 | # Put it under the base output dir with the same directory name | ||
73 | out_dir = "%s/%s" % (out_base_dir, sched_leaf_dir) | ||
74 | |||
75 | return (work_dir, out_dir) | ||
76 | |||
77 | |||
78 | def load_experiment(sched_file, scheduler, duration, param_file, out_base): | ||
79 | if not os.path.isfile(sched_file): | ||
80 | raise IOError("Cannot find schedule file: %s" % sched_file) | ||
81 | |||
82 | dirname = os.path.split(sched_file)[0] | ||
83 | |||
84 | if not scheduler or not duration: | ||
85 | param_file = param_file or \ | ||
86 | "%s/%s" % (dirname, conf.DEFAULTS['params_file']) | ||
87 | |||
88 | if os.path.isfile(param_file): | ||
89 | params = load_params(param_file) | ||
90 | scheduler = scheduler or params[conf.PARAMS['sched']] | ||
91 | duration = duration or params[conf.PARAMS['dur']] | ||
92 | |||
93 | duration = duration or conf.DEFAULTS['duration'] | ||
94 | |||
95 | if not scheduler: | ||
96 | raise IOError("Parameter scheduler not specified") | ||
97 | |||
98 | schedule = load_schedule(sched_file) | ||
99 | (work_dir, out_dir) = get_dirs(sched_file, out_base) | ||
100 | |||
101 | run_exp(sched_file, schedule, scheduler, duration, work_dir, out_dir) | ||
102 | |||
103 | |||
104 | def load_params(fname): | ||
105 | params = defaultdict(int) | ||
106 | with open(fname, 'r') as f: | ||
107 | data = f.read() | ||
108 | try: | ||
109 | parsed = eval(data) | ||
110 | for k in parsed: | ||
111 | params[k] = parsed[k] | ||
112 | except Exception as e: | ||
113 | raise IOError("Invalid param file: %s\n%s" % (fname, e)) | ||
114 | |||
115 | return params | ||
116 | |||
117 | |||
118 | def load_schedule(fname): | ||
119 | with open(fname, 'r') as f: | ||
120 | data = f.read() | ||
121 | try: | ||
122 | schedule = eval(data) | ||
123 | except: | ||
124 | schedule = convert_data(data) | ||
125 | return schedule | ||
126 | |||
127 | |||
128 | def run_exp(name, schedule, scheduler, duration, work_dir, out_dir): | ||
129 | proc_entries = [] | ||
130 | executables = [] | ||
131 | |||
132 | # Parse values for proc entries | ||
133 | for entry_conf in schedule['proc']: | ||
134 | path = entry_conf[0] | ||
135 | data = entry_conf[1] | ||
136 | |||
137 | if not os.path.exists(path): | ||
138 | raise IOError("Invalid proc path %s: %s" % (path, name)) | ||
139 | |||
140 | proc_entries += [ProcEntry(path, data)] | ||
141 | |||
142 | # Parse spinners | ||
143 | for spin_conf in schedule['spin']: | ||
144 | if isinstance(spin_conf, str): | ||
145 | # Just a string defaults to default spin | ||
146 | (spin, args) = (conf.DEFAULTS['spin'], spin_conf) | ||
147 | else: | ||
148 | # Otherwise its a pair, the type and the args | ||
149 | if len(spin_conf) != 2: | ||
150 | raise IOError("Invalid spin conf %s: %s" % (spin_conf, name)) | ||
151 | (spin, args) = (spin_conf[0], spin_conf[1]) | ||
152 | |||
153 | if not conf.BINS[spin]: | ||
154 | raise IndexError("No knowledge of program %s: %s" % (spin, name)) | ||
155 | |||
156 | real_spin = conf.BINS[spin] | ||
157 | real_args = ['-w'] + args.split() + [duration] | ||
158 | |||
159 | if not lu.is_executable(real_spin): | ||
160 | raise OSError("Cannot run spin %s: %s" % (real_spin, name)) | ||
161 | |||
162 | executables += [Executable(real_spin, real_args)] | ||
163 | |||
164 | exp = Experiment(name, scheduler, work_dir, out_dir, | ||
165 | proc_entries, executables) | ||
166 | exp.run_exp() | ||
167 | |||
168 | |||
169 | def main(): | ||
170 | opts, args = parse_args() | ||
171 | |||
172 | scheduler = opts.scheduler | ||
173 | duration = opts.duration | ||
174 | param_file = opts.param_file | ||
175 | out_base = os.path.abspath(opts.out_dir) | ||
176 | |||
177 | args = args or [opts.sched_file] | ||
178 | |||
179 | for exp in args: | ||
180 | path = "%s/%s" % (os.getcwd(), exp) | ||
181 | |||
182 | if not os.path.exists(path): | ||
183 | raise IOError("Invalid experiment: %s" % path) | ||
184 | |||
185 | if os.path.isdir(exp): | ||
186 | path = "%s%s" % (path, opts.sched_file) | ||
187 | |||
188 | load_experiment(path, scheduler, duration, param_file, out_base) | ||
189 | |||
190 | |||
191 | if __name__ == '__main__': | ||
192 | main() | ||