diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-03-18 14:24:35 -0400 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-03-18 14:24:35 -0400 |
commit | 57f52d18ca984a6328a04edbc1854407005e89cf (patch) | |
tree | c9f15a12db30f270c95136e6a89b138ec400a531 | |
parent | 0b49f91cd3f0e35acc6e3eeebf11f8d69aac834f (diff) |
Allow users to specify required kernel configuration options.
-rw-r--r-- | config/config.py | 1 | ||||
-rwxr-xr-x | run_exps.py | 53 |
2 files changed, 44 insertions, 10 deletions
diff --git a/config/config.py b/config/config.py index a6edece..75130fd 100644 --- a/config/config.py +++ b/config/config.py | |||
@@ -25,6 +25,7 @@ FILES = {'ft_data' : 'ft.bin', | |||
25 | PARAMS = {'sched' : 'scheduler', # Scheduler used by run_exps | 25 | PARAMS = {'sched' : 'scheduler', # Scheduler used by run_exps |
26 | 'dur' : 'duration', # Duration of tests in run_exps | 26 | 'dur' : 'duration', # Duration of tests in run_exps |
27 | 'kernel' : 'uname', # Regex of required OS name in run_exps | 27 | 'kernel' : 'uname', # Regex of required OS name in run_exps |
28 | 'copts' : 'config-options', # Required kernel configuration options | ||
28 | 'cycles' : 'clock-frequency', # Frequency run_exps was run with | 29 | 'cycles' : 'clock-frequency', # Frequency run_exps was run with |
29 | 'tasks' : 'tasks', # Number of tasks | 30 | 'tasks' : 'tasks', # Number of tasks |
30 | 'trial' : 'trial' # For multiple exps with same config | 31 | 'trial' : 'trial' # For multiple exps with same config |
diff --git a/run_exps.py b/run_exps.py index a05ff93..dc15701 100755 --- a/run_exps.py +++ b/run_exps.py | |||
@@ -1,13 +1,14 @@ | |||
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | from __future__ import print_function | 2 | from __future__ import print_function |
3 | 3 | ||
4 | import common as com | ||
4 | import config.config as conf | 5 | import config.config as conf |
5 | import os | 6 | import os |
6 | import re | 7 | import re |
7 | import shutil | 8 | import shutil |
8 | import traceback | 9 | import traceback |
9 | 10 | ||
10 | from common import load_params,get_executable,uname_matches,ft_freq | 11 | from collections import namedtuple |
11 | from optparse import OptionParser | 12 | from optparse import OptionParser |
12 | from run.executable.executable import Executable | 13 | from run.executable.executable import Executable |
13 | from run.experiment import Experiment,ExperimentDone | 14 | from run.experiment import Experiment,ExperimentDone |
@@ -21,6 +22,16 @@ class InvalidKernel(Exception): | |||
21 | def __str__(self): | 22 | def __str__(self): |
22 | return "Kernel '%s' does not match '%s'." % (self.kernel, self.wanted) | 23 | return "Kernel '%s' does not match '%s'." % (self.kernel, self.wanted) |
23 | 24 | ||
25 | ConfigResult = namedtuple('ConfigResult', ['param', 'wanted', 'actual']) | ||
26 | class InvalidConfig(Exception): | ||
27 | def __init__(self, results): | ||
28 | self.results = results | ||
29 | |||
30 | def __str__(self): | ||
31 | rstr = "'%s' - wanted: '%s', found: %s" | ||
32 | result = [rstr % (r.actual, r.param, r.wanted) for r in self.results] | ||
33 | return "Invalid kernel configuration\n" + result.join("\n") | ||
34 | |||
24 | def parse_args(): | 35 | def parse_args(): |
25 | parser = OptionParser("usage: %prog [options] [sched_file]... [exp_dir]...") | 36 | parser = OptionParser("usage: %prog [options] [sched_file]... [exp_dir]...") |
26 | 37 | ||
@@ -83,6 +94,23 @@ def fix_paths(schedule, exp_dir, sched_file): | |||
83 | 94 | ||
84 | schedule['spin'][idx] = (spin, args) | 95 | schedule['spin'][idx] = (spin, args) |
85 | 96 | ||
97 | def verify_environment(kernel, copts): | ||
98 | if kernel and not com.uname_matches(kernel): | ||
99 | raise InvalidKernel(kernel) | ||
100 | |||
101 | if copts: | ||
102 | results = [] | ||
103 | for param, wanted in copts.iteritems(): | ||
104 | try: | ||
105 | actual = com.get_config_option(param) | ||
106 | except IOError: | ||
107 | actual = None | ||
108 | if not str(wanted) == str(actual): | ||
109 | results += [ConfigResult(param, wanted, actual)] | ||
110 | |||
111 | if results: | ||
112 | raise InvalidKernel(results) | ||
113 | |||
86 | def load_experiment(sched_file, scheduler, duration, param_file, out_dir): | 114 | def load_experiment(sched_file, scheduler, duration, param_file, out_dir): |
87 | if not os.path.isfile(sched_file): | 115 | if not os.path.isfile(sched_file): |
88 | raise IOError("Cannot find schedule file: %s" % sched_file) | 116 | raise IOError("Cannot find schedule file: %s" % sched_file) |
@@ -97,13 +125,16 @@ def load_experiment(sched_file, scheduler, duration, param_file, out_dir): | |||
97 | "%s/%s" % (dir_name, conf.DEFAULTS['params_file']) | 125 | "%s/%s" % (dir_name, conf.DEFAULTS['params_file']) |
98 | 126 | ||
99 | if os.path.isfile(param_file): | 127 | if os.path.isfile(param_file): |
100 | params = load_params(param_file) | 128 | params = com.load_params(param_file) |
101 | scheduler = scheduler or params[conf.PARAMS['sched']] | 129 | scheduler = scheduler or params[conf.PARAMS['sched']] |
102 | duration = duration or params[conf.PARAMS['dur']] | 130 | duration = duration or params[conf.PARAMS['dur']] |
103 | 131 | ||
104 | # Experiments can specify required kernel name | 132 | # Experiments can specify required kernel name |
105 | if conf.PARAMS['kernel'] in params: | 133 | if conf.PARAMS['kernel'] in params: |
106 | kernel = params[conf.PARAMS['kernel']] | 134 | kernel = params[conf.PARAMS['kernel']] |
135 | # Or required config options | ||
136 | if conf.PARAMS['copts'] in params: | ||
137 | copts = params[conf.PARAMS['copts']] | ||
107 | 138 | ||
108 | duration = duration or conf.DEFAULTS['duration'] | 139 | duration = duration or conf.DEFAULTS['duration'] |
109 | 140 | ||
@@ -113,8 +144,11 @@ def load_experiment(sched_file, scheduler, duration, param_file, out_dir): | |||
113 | # Parse schedule file's intentions | 144 | # Parse schedule file's intentions |
114 | schedule = load_schedule(sched_file) | 145 | schedule = load_schedule(sched_file) |
115 | work_dir = "%s/tmp" % dir_name | 146 | work_dir = "%s/tmp" % dir_name |
147 | |||
116 | fix_paths(schedule, os.path.split(sched_file)[0], sched_file) | 148 | fix_paths(schedule, os.path.split(sched_file)[0], sched_file) |
117 | 149 | ||
150 | verify_environment(kernel, copts) | ||
151 | |||
118 | run_exp(exp_name, schedule, scheduler, kernel, duration, work_dir, out_dir) | 152 | run_exp(exp_name, schedule, scheduler, kernel, duration, work_dir, out_dir) |
119 | 153 | ||
120 | # Save parameters used to run experiment in out_dir | 154 | # Save parameters used to run experiment in out_dir |
@@ -124,7 +158,7 @@ def load_experiment(sched_file, scheduler, duration, param_file, out_dir): | |||
124 | (conf.PARAMS['dur'], duration)]) | 158 | (conf.PARAMS['dur'], duration)]) |
125 | 159 | ||
126 | # Feather-trace clock frequency saved for accurate overhead parsing | 160 | # Feather-trace clock frequency saved for accurate overhead parsing |
127 | ft_freq = ft_freq() | 161 | ft_freq = com.ft_freq() |
128 | if ft_freq: | 162 | if ft_freq: |
129 | out_params[conf.PARAMS['cycles']] = ft_freq | 163 | out_params[conf.PARAMS['cycles']] = ft_freq |
130 | 164 | ||
@@ -145,9 +179,6 @@ def run_exp(name, schedule, scheduler, kernel, duration, work_dir, out_dir): | |||
145 | proc_entries = [] | 179 | proc_entries = [] |
146 | executables = [] | 180 | executables = [] |
147 | 181 | ||
148 | if kernel and not uname_matches(kernel): | ||
149 | raise InvalidKernel(kernel) | ||
150 | |||
151 | # Parse values for proc entries | 182 | # Parse values for proc entries |
152 | for entry_conf in schedule['proc']: | 183 | for entry_conf in schedule['proc']: |
153 | path = entry_conf[0] | 184 | path = entry_conf[0] |
@@ -172,12 +203,12 @@ def run_exp(name, schedule, scheduler, kernel, duration, work_dir, out_dir): | |||
172 | # if not conf.BINS[spin]: | 203 | # if not conf.BINS[spin]: |
173 | # raise IndexError("No knowledge of program %s: %s" % (spin, name)) | 204 | # raise IndexError("No knowledge of program %s: %s" % (spin, name)) |
174 | 205 | ||
175 | real_spin = get_executable(spin, "") | 206 | real_spin = com.get_executable(spin, "") |
176 | real_args = args.split() | 207 | real_args = args.split() |
177 | if re.match(".*spin", real_spin): | 208 | if re.match(".*spin", real_spin): |
178 | real_args = ['-w'] + real_args + [duration] | 209 | real_args = ['-w'] + real_args + [duration] |
179 | 210 | ||
180 | if not is_executable(real_spin): | 211 | if not com.is_executable(real_spin): |
181 | raise OSError("Cannot run spin %s: %s" % (real_spin, name)) | 212 | raise OSError("Cannot run spin %s: %s" % (real_spin, name)) |
182 | 213 | ||
183 | executables += [Executable(real_spin, real_args)] | 214 | executables += [Executable(real_spin, real_args)] |
@@ -226,8 +257,10 @@ def main(): | |||
226 | except ExperimentDone: | 257 | except ExperimentDone: |
227 | done += 1 | 258 | done += 1 |
228 | print("Experiment '%s' already completed at '%s'" % (exp, out_base)) | 259 | print("Experiment '%s' already completed at '%s'" % (exp, out_base)) |
229 | except InvalidKernel: | 260 | except (InvalidKernel, InvalidConfig) as e: |
230 | invalid += 1 | 261 | invalid += 1 |
262 | print("Invalid environment for experiment '%s'") | ||
263 | print(e) | ||
231 | except: | 264 | except: |
232 | print("Failed experiment %s" % exp) | 265 | print("Failed experiment %s" % exp) |
233 | traceback.print_exc() | 266 | traceback.print_exc() |
@@ -240,7 +273,7 @@ def main(): | |||
240 | print(" Successful:\t\t%d" % succ) | 273 | print(" Successful:\t\t%d" % succ) |
241 | print(" Failed:\t\t%d" % failed) | 274 | print(" Failed:\t\t%d" % failed) |
242 | print(" Already Done:\t\t%d" % done) | 275 | print(" Already Done:\t\t%d" % done) |
243 | print(" Wrong Kernel:\t\t%d" % invalid) | 276 | print(" Invalid environment:\t\t%d" % invalid) |
244 | 277 | ||
245 | 278 | ||
246 | if __name__ == '__main__': | 279 | if __name__ == '__main__': |