diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-03-30 11:28:51 -0400 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-04-02 10:38:21 -0400 |
commit | 4b75d2b98036195b78d339210ab8d7512d9f2164 (patch) | |
tree | f7de0e91372f760ab8972c5e280023d57abb6b91 /gen/generator.py | |
parent | cb0dda981282df08c544e235f0fefb077268272c (diff) |
Added option to ignore environment issues and rewrote part of the generation scripts for easier generator creation.
Diffstat (limited to 'gen/generator.py')
-rw-r--r-- | gen/generator.py | 62 |
1 files changed, 46 insertions, 16 deletions
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 @@ | |||
1 | import gen.rv as rv | 1 | import gen.rv as rv |
2 | import os | 2 | import os |
3 | import pprint | ||
4 | import schedcat.generator.tasks as tasks | ||
3 | import shutil as sh | 5 | import shutil as sh |
4 | 6 | ||
5 | from Cheetah.Template import Template | 7 | from Cheetah.Template import Template |
6 | from collections import namedtuple | 8 | from common import get_config_option,num_cpus,recordtype |
7 | from common import get_config_option,num_cpus | ||
8 | from config.config import DEFAULTS,PARAMS | 9 | from config.config import DEFAULTS,PARAMS |
9 | from gen.dp import DesignPointGenerator | 10 | from gen.dp import DesignPointGenerator |
10 | from parse.col_map import ColMapBuilder | 11 | from 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''' |
38 | TP_RM = """#if $release_master | 40 | TP_RM = """#if $release_master |
39 | release_master{1} | 41 | release_master{0} |
40 | #end if""" | 42 | #end if""" |
41 | TP_TBASE = """#for $t in $task_set | ||
42 | {} $t.cost $t.period | ||
43 | #end for""" | ||
44 | TP_GLOB_TASK = TP_TBASE.format("") | ||
45 | TP_PART_TASK = TP_TBASE.format("-p $t.cpu") | ||
46 | 43 | ||
47 | GenOption = namedtuple('GenOption', ['name', 'types', 'default', 'help']) | 44 | GenOptionT = recordtype('GenOption', ['name', 'types', 'default', 'help', 'hidden']) |
45 | def GenOption(name, types, default, help, hidden = False): | ||
46 | return GenOptionT(name, types, default, help, hidden) | ||
48 | 47 | ||
49 | class Generator(object): | 48 | class 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)) |