aboutsummaryrefslogtreecommitdiffstats
path: root/run_exps.py
diff options
context:
space:
mode:
Diffstat (limited to 'run_exps.py')
-rwxr-xr-xrun_exps.py170
1 files changed, 92 insertions, 78 deletions
diff --git a/run_exps.py b/run_exps.py
index d7a06b5..a15018d 100755
--- a/run_exps.py
+++ b/run_exps.py
@@ -12,12 +12,13 @@ from config.config import PARAMS,DEFAULTS
12from collections import namedtuple 12from collections import namedtuple
13from optparse import OptionParser 13from optparse import OptionParser
14from run.executable.executable import Executable 14from run.executable.executable import Executable
15from run.experiment import Experiment,ExperimentDone,ExperimentFailed,SystemCorrupted 15from run.experiment import Experiment,ExperimentDone,SystemCorrupted
16from run.proc_entry import ProcEntry 16from run.proc_entry import ProcEntry
17 17
18'''Customizable experiment parameters''' 18'''Customizable experiment parameters'''
19ExpParams = namedtuple('ExpParams', ['scheduler', 'duration', 'tracers', 19ExpParams = namedtuple('ExpParams', ['scheduler', 'duration', 'tracers',
20 'kernel', 'config_options']) 20 'kernel', 'config_options', 'file_params',
21 'pre_script', 'post_script'])
21'''Comparison of requested versus actual kernel compile parameter value''' 22'''Comparison of requested versus actual kernel compile parameter value'''
22ConfigResult = namedtuple('ConfigResult', ['param', 'wanted', 'actual']) 23ConfigResult = namedtuple('ConfigResult', ['param', 'wanted', 'actual'])
23 24
@@ -113,8 +114,8 @@ def fix_paths(schedule, exp_dir, sched_file):
113 args = args.replace(arg, abspath) 114 args = args.replace(arg, abspath)
114 break 115 break
115 elif re.match(r'.*\w+\.[a-zA-Z]\w*', arg): 116 elif re.match(r'.*\w+\.[a-zA-Z]\w*', arg):
116 print("WARNING: non-existent file '%s' may be referenced:\n\t%s" 117 sys.stderr.write("WARNING: non-existent file '%s' " % arg +
117 % (arg, sched_file)) 118 "may be referenced:\n\t%s" % sched_file)
118 119
119 schedule['task'][idx] = (task, args) 120 schedule['task'][idx] = (task, args)
120 121
@@ -182,22 +183,21 @@ def verify_environment(exp_params):
182 raise InvalidConfig(results) 183 raise InvalidConfig(results)
183 184
184 185
185def run_parameter(exp_dir, out_dir, params, param_name): 186def run_script(script_params, exp, exp_dir, out_dir):
186 '''Run an executable (arguments optional) specified as a configurable 187 '''Run an executable (arguments optional)'''
187 @param_name in @params.''' 188 if not script_params:
188 if PARAMS[param_name] not in params:
189 return 189 return
190 190
191 script_params = params[PARAMS[param_name]]
192
193 # Split into arguments and program name 191 # Split into arguments and program name
194 if type(script_params) != type([]): 192 if type(script_params) != type([]):
195 script_params = [script_params] 193 script_params = [script_params]
196 script_name = script_params.pop(0)
197 194
195 exp.log("Running %s" % script_params.join(" "))
196
197 script_name = script_params.pop(0)
198 script = com.get_executable(script_name, cwd=exp_dir) 198 script = com.get_executable(script_name, cwd=exp_dir)
199 199
200 out = open('%s/%s-out.txt' % (out_dir, param_name), 'w') 200 out = open('%s/%s-out.txt' % (out_dir, script_name), 'w')
201 prog = Executable(script, script_params, cwd=out_dir, 201 prog = Executable(script, script_params, cwd=out_dir,
202 stderr_file=out, stdout_file=out) 202 stderr_file=out, stdout_file=out)
203 203
@@ -207,28 +207,41 @@ def run_parameter(exp_dir, out_dir, params, param_name):
207 out.close() 207 out.close()
208 208
209 209
210def get_exp_params(cmd_scheduler, cmd_duration, file_params): 210def make_exp_params(cmd_scheduler, cmd_duration, sched_dir, param_file):
211 '''Return ExpParam with configured values of all hardcoded params.''' 211 '''Return ExpParam with configured values of all hardcoded params.'''
212 kernel = copts = "" 212 kernel = copts = ""
213 213
214 scheduler = cmd_scheduler or file_params[PARAMS['sched']] 214 # Load parameter file
215 duration = cmd_duration or file_params[PARAMS['dur']] or\ 215 param_file = param_file or "%s/%s" % (sched_dir, DEFAULTS['params_file'])
216 if os.path.isfile(param_file):
217 fparams = com.load_params(param_file)
218 else:
219 fparams = {}
220
221 scheduler = cmd_scheduler or fparams[PARAMS['sched']]
222 duration = cmd_duration or fparams[PARAMS['dur']] or\
216 DEFAULTS['duration'] 223 DEFAULTS['duration']
217 224
218 # Experiments can specify required kernel name 225 # Experiments can specify required kernel name
219 if PARAMS['kernel'] in file_params: 226 if PARAMS['kernel'] in fparams:
220 kernel = file_params[PARAMS['kernel']] 227 kernel = fparams[PARAMS['kernel']]
221 228
222 # Or required config options 229 # Or required config options
223 if PARAMS['copts'] in file_params: 230 if PARAMS['copts'] in fparams:
224 copts = file_params[PARAMS['copts']] 231 copts = fparams[PARAMS['copts']]
225 232
226 # Or required tracers 233 # Or required tracers
227 requested = [] 234 requested = []
228 if PARAMS['trace'] in file_params: 235 if PARAMS['trace'] in fparams:
229 requested = file_params[PARAMS['trace']] 236 requested = fparams[PARAMS['trace']]
230 tracers = trace.get_tracer_types(requested) 237 tracers = trace.get_tracer_types(requested)
231 238
239 # Or scripts to run before and after experiments
240 def get_script(name):
241 return fparams[name] if name in fparams else None
242 pre_script = get_script('pre')
243 post_script = get_script('post')
244
232 # But only these two are mandatory 245 # But only these two are mandatory
233 if not scheduler: 246 if not scheduler:
234 raise IOError("No scheduler found in param file!") 247 raise IOError("No scheduler found in param file!")
@@ -236,48 +249,39 @@ def get_exp_params(cmd_scheduler, cmd_duration, file_params):
236 raise IOError("No duration found in param file!") 249 raise IOError("No duration found in param file!")
237 250
238 return ExpParams(scheduler=scheduler, kernel=kernel, duration=duration, 251 return ExpParams(scheduler=scheduler, kernel=kernel, duration=duration,
239 config_options=copts, tracers=tracers) 252 config_options=copts, tracers=tracers, file_params=fparams,
240 253 pre_script=pre_script, post_script=post_script)
241 254
242def load_experiment(sched_file, cmd_scheduler, cmd_duration, 255def run_experiment(name, sched_file, exp_params, out_dir,
243 param_file, out_dir, ignore, jabber): 256 start_message, ignore, jabber):
244 '''Load and parse data from files and run result.''' 257 '''Load and parse data from files and run result.'''
245 if not os.path.isfile(sched_file): 258 if not os.path.isfile(sched_file):
246 raise IOError("Cannot find schedule file: %s" % sched_file) 259 raise IOError("Cannot find schedule file: %s" % sched_file)
247 260
248 dir_name, fname = os.path.split(sched_file) 261 dir_name, fname = os.path.split(sched_file)
249 exp_name = os.path.split(dir_name)[1] + "/" + fname
250 work_dir = "%s/tmp" % dir_name 262 work_dir = "%s/tmp" % dir_name
251 263
252 # Load parameter file 264 procs, execs = load_schedule(name, sched_file, exp_params.duration)
253 param_file = param_file or \
254 "%s/%s" % (dir_name, DEFAULTS['params_file'])
255 if os.path.isfile(param_file):
256 file_params = com.load_params(param_file)
257 else:
258 file_params = {}
259
260 # Create input needed by Experiment
261 exp_params = get_exp_params(cmd_scheduler, cmd_duration, file_params)
262 procs, execs = load_schedule(exp_name, sched_file, exp_params.duration)
263 265
264 exp = Experiment(exp_name, exp_params.scheduler, work_dir, out_dir, 266 exp = Experiment(name, exp_params.scheduler, work_dir, out_dir,
265 procs, execs, exp_params.tracers) 267 procs, execs, exp_params.tracers)
266 268
269 exp.log(start_message)
270
267 if not ignore: 271 if not ignore:
268 verify_environment(exp_params) 272 verify_environment(exp_params)
269 273
270 run_parameter(dir_name, work_dir, file_params, 'pre') 274 run_script(exp_params.pre_script, exp, dir_name, work_dir)
271 275
272 exp.run_exp() 276 exp.run_exp()
273 277
274 run_parameter(dir_name, out_dir, file_params, 'post') 278 run_script(exp_params.post_script, exp, dir_name, out_dir)
275 279
276 if jabber: 280 if jabber:
277 jabber.send("Completed '%s'" % exp_name) 281 jabber.send("Completed '%s'" % name)
278 282
279 # Save parameters used to run experiment in out_dir 283 # Save parameters used to run experiment in out_dir
280 out_params = dict(file_params.items() + 284 out_params = dict(exp_params.file_params.items() +
281 [(PARAMS['sched'], exp_params.scheduler), 285 [(PARAMS['sched'], exp_params.scheduler),
282 (PARAMS['tasks'], len(execs)), 286 (PARAMS['tasks'], len(execs)),
283 (PARAMS['dur'], exp_params.duration)]) 287 (PARAMS['dur'], exp_params.duration)])
@@ -292,6 +296,7 @@ def load_experiment(sched_file, cmd_scheduler, cmd_duration,
292 296
293 297
294def get_exps(opts, args): 298def get_exps(opts, args):
299 '''Return list of experiment files or directories'''
295 if args: 300 if args:
296 return args 301 return args
297 302
@@ -333,63 +338,72 @@ def setup_email(target):
333 return None 338 return None
334 339
335 340
341def make_paths(exp, out_base_dir, opts):
342 '''Translate experiment name to (schedule file, output directory) paths'''
343 path = "%s/%s" % (os.getcwd(), exp)
344 out_dir = "%s/%s" % (out_base_dir, os.path.split(exp.strip('/'))[1])
345
346 if not os.path.exists(path):
347 raise IOError("Invalid experiment: %s" % path)
348
349 if opts.force and os.path.exists(out_dir):
350 shutil.rmtree(out_dir)
351
352 if os.path.isdir(path):
353 sched_file = "%s/%s" % (path, opts.sched_file)
354 else:
355 sched_file = path
356
357 return sched_file, out_dir
358
359
336def main(): 360def main():
337 opts, args = parse_args() 361 opts, args = parse_args()
338 362
339 scheduler = opts.scheduler
340 duration = opts.duration
341 param_file = opts.param_file
342 out_base = os.path.abspath(opts.out_dir)
343
344 exps = get_exps(opts, args) 363 exps = get_exps(opts, args)
345 364
346 created = False 365 jabber = setup_jabber(opts.jabber) if opts.jabber else None
366 email = setup_email(opts.email) if opts.email else None
367
368 out_base = os.path.abspath(opts.out_dir)
369 created = False
347 if not os.path.exists(out_base): 370 if not os.path.exists(out_base):
348 created = True 371 created = True
349 os.mkdir(out_base) 372 os.mkdir(out_base)
350 373
351 ran = 0 374 ran = done = succ = failed = invalid = 0
352 done = 0
353 succ = 0
354 failed = 0
355 invalid = 0
356
357 jabber = setup_jabber(opts.jabber) if opts.jabber else None
358 email = setup_email(opts.email) if opts.email else None
359
360 for exp in exps:
361 path = "%s/%s" % (os.getcwd(), exp)
362 out_dir = "%s/%s" % (out_base, os.path.split(exp.strip('/'))[1])
363 375
364 if not os.path.exists(path): 376 for i, exp in enumerate(exps):
365 raise IOError("Invalid experiment: %s" % path) 377 sched_file, out_dir = make_paths(exp, out_base, opts)
378 sched_dir = os.path.split(sched_file)[0]
366 379
367 if opts.force and os.path.exists(out_dir): 380 try:
368 shutil.rmtree(out_dir) 381 start_message = "Loading experiment %d of %d." % (i+1, len(exps))
382 exp_params = make_exp_params(opts.scheduler, opts.duration,
383 sched_dir, opts.param_file)
369 384
370 if os.path.isdir(exp): 385 run_experiment(exp, sched_file, exp_params, out_dir,
371 path = "%s/%s" % (path, opts.sched_file) 386 start_message, opts.ignore, jabber)
372 387
373 try:
374 load_experiment(path, scheduler, duration, param_file,
375 out_dir, opts.ignore, jabber)
376 succ += 1 388 succ += 1
377 except ExperimentDone: 389 except ExperimentDone:
390 sys.stderr.write("Experiment '%s' already completed " % exp +
391 "at '%s'\n" % out_base)
378 done += 1 392 done += 1
379 print("Experiment '%s' already completed at '%s'" % (exp, out_base))
380 except (InvalidKernel, InvalidConfig) as e: 393 except (InvalidKernel, InvalidConfig) as e:
394 sys.stderr.write("Invalid environment for experiment '%s'\n" % exp)
395 sys.stderr.write("%s\n" % e)
381 invalid += 1 396 invalid += 1
382 print("Invalid environment for experiment '%s'" % exp)
383 print(e)
384 except KeyboardInterrupt: 397 except KeyboardInterrupt:
385 print("Keyboard interrupt, quitting") 398 sys.stderr.write("Keyboard interrupt, quitting\n")
386 break 399 break
387 except SystemCorrupted as e: 400 except SystemCorrupted as e:
388 print("System is corrupted! Fix state before continuing.") 401 sys.stderr.write("System is corrupted! Fix state before continuing.\n")
389 print(e) 402 sys.stderr.write("%s\n" % e)
390 break 403 break
391 except ExperimentFailed: 404 except Exception as e:
392 print("Failed experiment %s" % exp) 405 sys.stderr.write("Failed experiment %s\n" % exp)
406 sys.stderr.write("%s\n" % e)
393 failed += 1 407 failed += 1
394 408
395 ran += 1 409 ran += 1
@@ -398,7 +412,7 @@ def main():
398 if not os.listdir(out_base) and created and not succ: 412 if not os.listdir(out_base) and created and not succ:
399 os.rmdir(out_base) 413 os.rmdir(out_base)
400 414
401 message = "Experiments ran:\t%d of %d" % (ran, len(args)) +\ 415 message = "Experiments ran:\t%d of %d" % (ran, len(exps)) +\
402 "\n Successful:\t\t%d" % succ +\ 416 "\n Successful:\t\t%d" % succ +\
403 "\n Failed:\t\t%d" % failed +\ 417 "\n Failed:\t\t%d" % failed +\
404 "\n Already Done:\t\t%d" % done +\ 418 "\n Already Done:\t\t%d" % done +\