aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common.py11
-rw-r--r--gen/edf_generators.py30
-rw-r--r--gen/generator.py62
-rwxr-xr-xgen_exps.py4
-rw-r--r--run/proc_entry.py7
-rwxr-xr-xrun_exps.py28
6 files changed, 93 insertions, 49 deletions
diff --git a/common.py b/common.py
index cba31bf..a26ac94 100644
--- a/common.py
+++ b/common.py
@@ -50,6 +50,12 @@ def get_config_option(option):
50 else: 50 else:
51 raise IOError("No config file exists!") 51 raise IOError("No config file exists!")
52 52
53def try_get_config_option(option, default):
54 try:
55 get_config_option(option)
56 except:
57 return default
58
53def recordtype(typename, field_names, default=0): 59def recordtype(typename, field_names, default=0):
54 ''' Mutable namedtuple. Recipe from George Sakkis of MIT.''' 60 ''' Mutable namedtuple. Recipe from George Sakkis of MIT.'''
55 field_names = tuple(map(str, field_names)) 61 field_names = tuple(map(str, field_names))
@@ -127,10 +133,7 @@ def load_params(fname):
127 with open(fname, 'r') as f: 133 with open(fname, 'r') as f:
128 data = f.read() 134 data = f.read()
129 try: 135 try:
130 parsed = eval(data) 136 params = eval(data)
131 # Convert to defaultdict
132 for k in parsed:
133 params[k] = str(parsed[k])
134 except Exception as e: 137 except Exception as e:
135 raise IOError("Invalid param file: %s\n%s" % (fname, e)) 138 raise IOError("Invalid param file: %s\n%s" % (fname, e))
136 139
diff --git a/gen/edf_generators.py b/gen/edf_generators.py
index c7267f7..9bf6b8f 100644
--- a/gen/edf_generators.py
+++ b/gen/edf_generators.py
@@ -1,15 +1,20 @@
1import generator as gen 1import generator as gen
2import random 2import random
3import schedcat.generator.tasks as tasks 3
4TP_TBASE = """#for $t in $task_set
5{} $t.cost $t.period
6#end for"""
7TP_GLOB_TASK = TP_TBASE.format("")
8TP_PART_TASK = TP_TBASE.format("-p $t.cpu")
4 9
5class EdfGenerator(gen.Generator): 10class EdfGenerator(gen.Generator):
6 '''Creates sporadic task sets with the most common Litmus options.''' 11 '''Creates sporadic task sets with the most common Litmus options.'''
7 def __init__(self, name, templates, options, params): 12 def __init__(self, name, templates, options, params):
8 super(EdfGenerator, self).__init__(name, templates, 13 super(EdfGenerator, self).__init__(name, templates,
9 self.__make_options(params) + options, 14 self.__make_options() + options,
10 params) 15 params)
11 16
12 def __make_options(self, params): 17 def __make_options(self):
13 '''Return generic EDF options.''' 18 '''Return generic EDF options.'''
14 return [gen.Generator._dist_option('utils', ['uni-medium'], 19 return [gen.Generator._dist_option('utils', ['uni-medium'],
15 gen.NAMED_UTILIZATIONS, 20 gen.NAMED_UTILIZATIONS,
@@ -26,23 +31,12 @@ class EdfGenerator(gen.Generator):
26 udist = self._create_dist('utilization', 31 udist = self._create_dist('utilization',
27 exp_params['utils'], 32 exp_params['utils'],
28 gen.NAMED_UTILIZATIONS) 33 gen.NAMED_UTILIZATIONS)
29 tg = tasks.TaskGenerator(period=pdist, util=udist)
30 34
31 ts = [] 35 ts = self._create_taskset(exp_params, pdist, udist)
32 tries = 0
33 while len(ts) != exp_params['num_tasks'] and tries < 5:
34 ts = tg.make_task_set(max_tasks = exp_params['num_tasks'])
35 tries += 1
36 if len(ts) != exp_params['num_tasks']:
37 print("Failed to create task set with parameters: %s" % exp_params)
38 36
39 self._customize(ts, exp_params) 37 self._customize(ts, exp_params)
40 38
41 exp_params['task_set'] = ts 39 self._write_schedule(dict(exp_params.items() + ('task_set', ts)))
42 self._write_schedule(exp_params)
43
44 del exp_params['task_set']
45 del exp_params['num_tasks']
46 self._write_params(exp_params) 40 self._write_params(exp_params)
47 41
48 def _customize(self, taskset, exp_params): 42 def _customize(self, taskset, exp_params):
@@ -53,7 +47,7 @@ class EdfGenerator(gen.Generator):
53class PartitionedGenerator(EdfGenerator): 47class PartitionedGenerator(EdfGenerator):
54 def __init__(self, name, templates, options, params): 48 def __init__(self, name, templates, options, params):
55 super(PartitionedGenerator, self).__init__(name, 49 super(PartitionedGenerator, self).__init__(name,
56 templates + [gen.TP_PART_TASK], options, params) 50 templates + [TP_PART_TASK], options, params)
57 51
58 def _customize(self, taskset, exp_params): 52 def _customize(self, taskset, exp_params):
59 start = 1 if exp_params['release_master'] else 0 53 start = 1 if exp_params['release_master'] else 0
@@ -78,5 +72,5 @@ class CedfGenerator(PartitionedGenerator):
78 72
79class GedfGenerator(EdfGenerator): 73class GedfGenerator(EdfGenerator):
80 def __init__(self, params={}): 74 def __init__(self, params={}):
81 super(GedfGenerator, self).__init__("GSN-EDF", [gen.TP_GLOB_TASK], 75 super(GedfGenerator, self).__init__("GSN-EDF", [TP_GLOB_TASK],
82 [], params) 76 [], params)
diff --git a/gen/generator.py b/gen/generator.py
index 8c3048b..3a6524d 100644
--- a/gen/generator.py
+++ b/gen/generator.py
@@ -1,10 +1,11 @@
1import gen.rv as rv 1import gen.rv as rv
2import os 2import os
3import pprint
4import schedcat.generator.tasks as tasks
3import shutil as sh 5import shutil as sh
4 6
5from Cheetah.Template import Template 7from Cheetah.Template import Template
6from collections import namedtuple 8from common import get_config_option,num_cpus,recordtype
7from common import get_config_option,num_cpus
8from config.config import DEFAULTS,PARAMS 9from config.config import DEFAULTS,PARAMS
9from gen.dp import DesignPointGenerator 10from gen.dp import DesignPointGenerator
10from parse.col_map import ColMapBuilder 11from parse.col_map import ColMapBuilder
@@ -21,6 +22,7 @@ NAMED_UTILIZATIONS = {
21 'uni-light' : rv.uniform(0.001, 0.1), 22 'uni-light' : rv.uniform(0.001, 0.1),
22 'uni-medium' : rv.uniform( 0.1, 0.4), 23 'uni-medium' : rv.uniform( 0.1, 0.4),
23 'uni-heavy' : rv.uniform( 0.5, 0.9), 24 'uni-heavy' : rv.uniform( 0.5, 0.9),
25 'uni-mixed' : rv.uniform(0.001, .4),
24 26
25 'exp-light' : rv.exponential(0, 1, 0.10), 27 'exp-light' : rv.exponential(0, 1, 0.10),
26 'exp-medium' : rv.exponential(0, 1, 0.25), 28 'exp-medium' : rv.exponential(0, 1, 0.25),
@@ -36,15 +38,12 @@ NAMED_UTILIZATIONS = {
36 38
37'''Components of Cheetah template for schedule file''' 39'''Components of Cheetah template for schedule file'''
38TP_RM = """#if $release_master 40TP_RM = """#if $release_master
39release_master{1} 41release_master{0}
40#end if""" 42#end if"""
41TP_TBASE = """#for $t in $task_set
42{} $t.cost $t.period
43#end for"""
44TP_GLOB_TASK = TP_TBASE.format("")
45TP_PART_TASK = TP_TBASE.format("-p $t.cpu")
46 43
47GenOption = namedtuple('GenOption', ['name', 'types', 'default', 'help']) 44GenOptionT = recordtype('GenOption', ['name', 'types', 'default', 'help', 'hidden'])
45def GenOption(name, types, default, help, hidden = False):
46 return GenOptionT(name, types, default, help, hidden)
48 47
49class Generator(object): 48class Generator(object):
50 '''Creates all combinations @options specified by @params. 49 '''Creates all combinations @options specified by @params.
@@ -92,36 +91,65 @@ class Generator(object):
92 def _create_dist(self, name, value, named_dists): 91 def _create_dist(self, name, value, named_dists):
93 '''Attempt to create a distribution representing the data in @value. 92 '''Attempt to create a distribution representing the data in @value.
94 If @value is a string, use it as a key for @named_dists.''' 93 If @value is a string, use it as a key for @named_dists.'''
95 name = "%s distribution" % name
96 # A list of values 94 # A list of values
97 if type(value) == type([]): 95 if type(value) == type([]):
98 map(lambda x : self.__check_value(name, x, [float, int]), value) 96 map(lambda x : self.__check_value(name, x, [float, int]), value)
99 return rv.uniform_choice(value) 97 return rv.uniform_choice(value)
100 elif type(value) in [float, int]: 98 elif type(value) in [float, int]:
101 return lambda : value 99 return lambda : value
102 elif value in named_dists: 100 elif named_dists and value in named_dists:
103 return named_dists[value] 101 return named_dists[value]
104 else: 102 else:
105 raise ValueError("Invalid %s value: %s" % (name, value)) 103 raise ValueError("Invalid %s value: %s" % (name, value))
106 104
105 def _create_taskset(self, params, periods, utils, max_util = None):
106 tg = tasks.TaskGenerator(period=periods, util=utils)
107 ts = []
108 tries = 0
109 while len(ts) != params['num_tasks'] and tries < 100:
110 ts = tg.make_task_set(max_tasks = params['num_tasks'], max_util=max_util)
111 tries += 1
112 if len(ts) != params['num_tasks']:
113 print(("Only created task set of size %d < %d for params %s. " +
114 "Switching to light utilization.") %
115 (len(ts), params['num_tasks'], params))
116 print("Switching to light util. This usually means the " +
117 "utilization distribution is too agressive.")
118 return self._create_taskset(params, periods, NAMED_UTILIZATIONS['uni-light'],
119 max_util)
120 return ts
121
107 def _write_schedule(self, params): 122 def _write_schedule(self, params):
108 '''Write schedule file using current template for @params.''' 123 '''Write schedule file using current template for @params.'''
109 sched_file = self.out_dir + "/" + DEFAULTS['sched_file'] 124 sched_file = self.out_dir + "/" + DEFAULTS['sched_file']
110 with open(sched_file, 'wa') as f: 125 with open(sched_file, 'wa') as f:
111 f.write(str(Template(self.template, searchList=[params]))) 126 f.write(str(Template(self.template, searchList=[params])))
112 127
128
113 def _write_params(self, params): 129 def _write_params(self, params):
114 '''Write out file with relevant parameters.''' 130 '''Write out file with relevant parameters.'''
131 # Don't include this in the parameters. It will be automatically added
132 # in run_exps.py
133 if 'num_tasks' in params:
134 num_tasks = params.pop('num_tasks')
135 else:
136 num_tasks = 0
137
115 exp_params_file = self.out_dir + "/" + DEFAULTS['params_file'] 138 exp_params_file = self.out_dir + "/" + DEFAULTS['params_file']
116 with open(exp_params_file, 'wa') as f: 139 with open(exp_params_file, 'wa') as f:
117 params['scheduler'] = self.name 140 params['scheduler'] = self.name
118 f.write(str(params)) 141 pprint.pprint(params, f)
142
143 if num_tasks:
144 params['num_tasks'] = num_tasks
119 145
120 def __setup_params(self, params): 146 def __setup_params(self, params):
121 '''Set default parameter values and check that values are valid.''' 147 '''Set default parameter values and check that values are valid.'''
122 for option in self.options: 148 for option in self.options:
123 if option.name not in params: 149 if option.name not in params:
124 params[option.name] = option.default 150 params[option.name] = option.default
151 else:
152 option.hidden = True
125 params[option.name] = self._check_value(option.name, 153 params[option.name] = self._check_value(option.name,
126 option.types, 154 option.types,
127 params[option.name]) 155 params[option.name])
@@ -207,14 +235,16 @@ class Generator(object):
207 if PARAMS['trial'] in dp: 235 if PARAMS['trial'] in dp:
208 del dp[PARAMS['trial']] 236 del dp[PARAMS['trial']]
209 237
238 HELP_INDENT = 17
210 239
211 def print_help(self): 240 def print_help(self):
241 display_options = [o for o in self.options if not o.hidden]
212 s = str(Template("""Generator $name: 242 s = str(Template("""Generator $name:
213 #for $o in $options 243 #for $o in $options
214 $o.name -- $o.help 244 $o.name -- $o.help
215 \tDefault: $o.default 245 \tDefault: $o.default
216 \tAllowed: $o.types 246 \tAllowed: $o.types
217 #end for""", searchList=vars(self))) 247 #end for""", searchList={'name':self.name, 'options':display_options}))
218 248
219 # Has to be an easier way to print this out... 249 # Has to be an easier way to print this out...
220 for line in s.split("\n"): 250 for line in s.split("\n"):
@@ -223,8 +253,8 @@ class Generator(object):
223 for word in line.split(", "): 253 for word in line.split(", "):
224 i += len(word) 254 i += len(word)
225 res += [word] 255 res += [word]
226 if i > 80: 256 if i > 80 and len(word) < 80:
227 print(", ".join(res[:-1])) 257 print(", ".join(res[:-1]))
228 res = ["\t\t "+res[-1]] 258 res = [" "*Generator.HELP_INDENT +res[-1]]
229 i = line.index("'") 259 i = Generator.HELP_INDENT + len(word)
230 print(", ".join(res)) 260 print(", ".join(res))
diff --git a/gen_exps.py b/gen_exps.py
index 20a6c6f..cb05fe7 100755
--- a/gen_exps.py
+++ b/gen_exps.py
@@ -6,12 +6,14 @@ import re
6import shutil as sh 6import shutil as sh
7 7
8from gen.edf_generators import GedfGenerator,PedfGenerator,CedfGenerator 8from gen.edf_generators import GedfGenerator,PedfGenerator,CedfGenerator
9from gen.mc_generators import McGenerator
9from optparse import OptionParser 10from optparse import OptionParser
10 11
11# There has to be a better way to do this... 12# There has to be a better way to do this...
12GENERATORS = {'C-EDF':CedfGenerator, 13GENERATORS = {'C-EDF':CedfGenerator,
13 'P-EDF':PedfGenerator, 14 'P-EDF':PedfGenerator,
14 'G-EDF':GedfGenerator} 15 'G-EDF':GedfGenerator,
16 'MC':McGenerator}
15 17
16def parse_args(): 18def parse_args():
17 parser = OptionParser("usage: %prog [options] [files...] " 19 parser = OptionParser("usage: %prog [options] [files...] "
diff --git a/run/proc_entry.py b/run/proc_entry.py
index 0b7f9ce..4ac2c51 100644
--- a/run/proc_entry.py
+++ b/run/proc_entry.py
@@ -8,5 +8,8 @@ class ProcEntry(object):
8 def write_proc(self): 8 def write_proc(self):
9 if not os.path.exists(self.proc): 9 if not os.path.exists(self.proc):
10 raise Exception("Invalid proc entry %s" % self.proc) 10 raise Exception("Invalid proc entry %s" % self.proc)
11 with open(self.proc, 'w') as entry: 11 try:
12 entry.write(self.data) 12 with open(self.proc, 'w') as entry:
13 entry.write(self.data)
14 except:
15 print("Failed to write into %s value:\n%s" % (self.proc, self.data))
diff --git a/run_exps.py b/run_exps.py
index 6873877..4a2d8ab 100755
--- a/run_exps.py
+++ b/run_exps.py
@@ -27,15 +27,24 @@ class InvalidConfig(Exception):
27 self.results = results 27 self.results = results
28 28
29 def __str__(self): 29 def __str__(self):
30 rstr = "'%s' - wanted: '%s', found: %s" 30 rstr = "'%s'%swanted: '%s', found: %s"
31 result = [rstr % (r.actual, r.param, r.wanted) for r in self.results] 31 messages = []
32 return "Invalid kernel configuration\n" + result.join("\n") 32 for r in self.results:
33 # For pretty alignment
34 tabs = (3 - len(r.param)/8)
35 messages += [rstr % (r.param, '\t'*tabs, r.wanted, r.actual)]
36
37 return "Invalid kernel configuration " +\
38 "(ignore configuration with -i option).\n" + "\n".join(messages)
33 39
34def parse_args(): 40def parse_args():
35 parser = OptionParser("usage: %prog [options] [sched_file]... [exp_dir]...") 41 parser = OptionParser("usage: %prog [options] [sched_file]... [exp_dir]...")
36 42
37 parser.add_option('-s', '--scheduler', dest='scheduler', 43 parser.add_option('-s', '--scheduler', dest='scheduler',
38 help='scheduler for all experiments') 44 help='scheduler for all experiments')
45 parser.add_option('-i', '--ignore-environment', dest='ignore',
46 action='store_true', default=False,
47 help='run experiments even in invalid environments ')
39 parser.add_option('-d', '--duration', dest='duration', type='int', 48 parser.add_option('-d', '--duration', dest='duration', type='int',
40 help='duration (seconds) of tasks') 49 help='duration (seconds) of tasks')
41 parser.add_option('-o', '--out-dir', dest='out_dir', 50 parser.add_option('-o', '--out-dir', dest='out_dir',
@@ -87,7 +96,7 @@ def fix_paths(schedule, exp_dir, sched_file):
87 if os.path.exists(abspath): 96 if os.path.exists(abspath):
88 args = args.replace(arg, abspath) 97 args = args.replace(arg, abspath)
89 break 98 break
90 elif re.match(r'.*\w+\.\w+', arg): 99 elif re.match(r'.*\w+\.[a-zA-Z]\w*', arg):
91 print("WARNING: non-existent file '%s' may be referenced:\n\t%s" 100 print("WARNING: non-existent file '%s' may be referenced:\n\t%s"
92 % (arg, sched_file)) 101 % (arg, sched_file))
93 102
@@ -108,9 +117,10 @@ def verify_environment(kernel, copts):
108 results += [ConfigResult(param, wanted, actual)] 117 results += [ConfigResult(param, wanted, actual)]
109 118
110 if results: 119 if results:
111 raise InvalidKernel(results) 120 raise InvalidConfig(results)
112 121
113def load_experiment(sched_file, scheduler, duration, param_file, out_dir): 122def load_experiment(sched_file, scheduler, duration,
123 param_file, out_dir, ignore):
114 if not os.path.isfile(sched_file): 124 if not os.path.isfile(sched_file):
115 raise IOError("Cannot find schedule file: %s" % sched_file) 125 raise IOError("Cannot find schedule file: %s" % sched_file)
116 126
@@ -146,7 +156,8 @@ def load_experiment(sched_file, scheduler, duration, param_file, out_dir):
146 156
147 fix_paths(schedule, os.path.split(sched_file)[0], sched_file) 157 fix_paths(schedule, os.path.split(sched_file)[0], sched_file)
148 158
149 verify_environment(kernel, copts) 159 if not ignore:
160 verify_environment(kernel, copts)
150 161
151 run_exp(exp_name, schedule, scheduler, kernel, duration, work_dir, out_dir) 162 run_exp(exp_name, schedule, scheduler, kernel, duration, work_dir, out_dir)
152 163
@@ -251,7 +262,8 @@ def main():
251 path = "%s/%s" % (path, opts.sched_file) 262 path = "%s/%s" % (path, opts.sched_file)
252 263
253 try: 264 try:
254 load_experiment(path, scheduler, duration, param_file, out_dir) 265 load_experiment(path, scheduler, duration, param_file,
266 out_dir, opts.ignore)
255 succ += 1 267 succ += 1
256 except ExperimentDone: 268 except ExperimentDone:
257 done += 1 269 done += 1