diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-04-23 17:28:12 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-04-23 17:28:12 -0400 |
| commit | 2ceaa6c607ef85bde4f14017634d9d1621efca29 (patch) | |
| tree | c85e755e59907a48ff762fd56473449f33c23894 /gen | |
| parent | a0e4b9fe9d7fab9a50a626cfeda3c614a9a6af5d (diff) | |
| parent | 7545402506aa76261e18d85af585ff0ac1cf05c1 (diff) | |
Merge branch 'master' into wip-color-mc
Conflicts:
gen/generator.py
parse/sched.py
parse_exps.py
Diffstat (limited to 'gen')
| -rw-r--r-- | gen/edf_generators.py | 24 | ||||
| -rw-r--r-- | gen/generator.py | 24 | ||||
| -rw-r--r-- | gen/mc_generators.py | 82 |
3 files changed, 95 insertions, 35 deletions
diff --git a/gen/edf_generators.py b/gen/edf_generators.py index 3f05b76..a722c21 100644 --- a/gen/edf_generators.py +++ b/gen/edf_generators.py | |||
| @@ -16,10 +16,10 @@ class EdfGenerator(gen.Generator): | |||
| 16 | 16 | ||
| 17 | def __make_options(self): | 17 | def __make_options(self): |
| 18 | '''Return generic EDF options.''' | 18 | '''Return generic EDF options.''' |
| 19 | return [gen.Generator._dist_option('utils', ['uni-medium'], | 19 | return [gen.Generator._dist_option('utils', 'uni-medium', |
| 20 | gen.NAMED_UTILIZATIONS, | 20 | gen.NAMED_UTILIZATIONS, |
| 21 | 'Task utilization distributions.'), | 21 | 'Task utilization distributions.'), |
| 22 | gen.Generator._dist_option('periods', ['harmonic'], | 22 | gen.Generator._dist_option('periods', 'harmonic', |
| 23 | gen.NAMED_PERIODS, | 23 | gen.NAMED_PERIODS, |
| 24 | 'Task period distributions.')] | 24 | 'Task period distributions.')] |
| 25 | 25 | ||
| @@ -50,10 +50,22 @@ class PartitionedGenerator(EdfGenerator): | |||
| 50 | templates + [TP_PART_TASK], options, params) | 50 | templates + [TP_PART_TASK], options, params) |
| 51 | 51 | ||
| 52 | def _customize(self, taskset, exp_params): | 52 | def _customize(self, taskset, exp_params): |
| 53 | start = 1 if exp_params['release_master'] else 0 | 53 | cpus = exp_params['cpus'] |
| 54 | # Random partition for now: could do a smart partitioning | 54 | start = 0 |
| 55 | if exp_params['release_master']: | ||
| 56 | cpus -= 1 | ||
| 57 | start = 1 | ||
| 58 | |||
| 59 | # Partition using worst-fit for most even distribution | ||
| 60 | utils = [0]*cpus | ||
| 61 | tasks = [0]*cpus | ||
| 55 | for t in taskset: | 62 | for t in taskset: |
| 56 | t.cpu = random.randint(start, exp_params['cpus'] - 1) | 63 | t.cpu = utils.index(min(utils)) |
| 64 | utils[t.cpu] += t.utilization() | ||
| 65 | tasks[t.cpu] += 1 | ||
| 66 | |||
| 67 | # Increment by one so release master has no tasks | ||
| 68 | t.cpu += start | ||
| 57 | 69 | ||
| 58 | class PedfGenerator(PartitionedGenerator): | 70 | class PedfGenerator(PartitionedGenerator): |
| 59 | def __init__(self, params={}): | 71 | def __init__(self, params={}): |
| @@ -61,7 +73,7 @@ class PedfGenerator(PartitionedGenerator): | |||
| 61 | 73 | ||
| 62 | class CedfGenerator(PartitionedGenerator): | 74 | class CedfGenerator(PartitionedGenerator): |
| 63 | TP_CLUSTER = "plugins/C-EDF/cluster{$level}" | 75 | TP_CLUSTER = "plugins/C-EDF/cluster{$level}" |
| 64 | CLUSTER_OPTION = gen.GenOption('level', ['L2', 'L3', 'All'], ['L2'], | 76 | CLUSTER_OPTION = gen.GenOption('level', ['L2', 'L3', 'All'], 'L2', |
| 65 | 'Cache clustering level.',) | 77 | 'Cache clustering level.',) |
| 66 | 78 | ||
| 67 | def __init__(self, params={}): | 79 | def __init__(self, params={}): |
diff --git a/gen/generator.py b/gen/generator.py index 693e52f..bc86cfe 100644 --- a/gen/generator.py +++ b/gen/generator.py | |||
| @@ -5,7 +5,7 @@ import schedcat.generator.tasks as tasks | |||
| 5 | import shutil as sh | 5 | import shutil as sh |
| 6 | 6 | ||
| 7 | from Cheetah.Template import Template | 7 | from Cheetah.Template import Template |
| 8 | from common import get_config_option,num_cpus,recordtype | 8 | from common import get_config_option,num_cpus,recordtype,log_once |
| 9 | from config.config import DEFAULTS,PARAMS | 9 | from config.config import DEFAULTS,PARAMS |
| 10 | from gen.dp import DesignPointGenerator | 10 | from gen.dp import DesignPointGenerator |
| 11 | from parse.col_map import ColMapBuilder | 11 | from parse.col_map import ColMapBuilder |
| @@ -69,11 +69,10 @@ class Generator(object): | |||
| 69 | else: | 69 | else: |
| 70 | self.cpus = num_cpus() | 70 | self.cpus = num_cpus() |
| 71 | try: | 71 | try: |
| 72 | config = get_config_option("RELEASE_MASTER") and True | 72 | rm_config = get_config_option("RELEASE_MASTER") and True |
| 73 | except: | 73 | except: |
| 74 | config = False | 74 | rm_config = False |
| 75 | self.release_master = list(set([False, config])) | 75 | self.release_master = list(set([False, bool(rm_config)])) |
| 76 | |||
| 77 | 76 | ||
| 78 | def __make_options(self, params): | 77 | def __make_options(self, params): |
| 79 | '''Return generic Litmus options.''' | 78 | '''Return generic Litmus options.''' |
| @@ -116,11 +115,11 @@ class Generator(object): | |||
| 116 | ts = tg.make_task_set(max_tasks = params['tasks'], max_util=max_util) | 115 | ts = tg.make_task_set(max_tasks = params['tasks'], max_util=max_util) |
| 117 | tries += 1 | 116 | tries += 1 |
| 118 | if len(ts) != params['tasks']: | 117 | if len(ts) != params['tasks']: |
| 119 | print(("Only created task set of size %d < %d for params %s. " + | 118 | log_once("only", ("Only created task set of size %d < %d for " + |
| 120 | "Switching to light utilization.") % | 119 | "params %s. Switching to light utilization.") % |
| 121 | (len(ts), params['tasks'], params)) | 120 | (len(ts), params['tasks'], params)) |
| 122 | print("Switching to light util. This usually means the " + | 121 | log_once("light", "Switching to light util. This usually means " + |
| 123 | "utilization distribution is too agressive.") | 122 | "the utilization distribution is too agressive.") |
| 124 | return self._create_taskset(params, periods, NAMED_UTILIZATIONS['uni-light'], | 123 | return self._create_taskset(params, periods, NAMED_UTILIZATIONS['uni-light'], |
| 125 | max_util) | 124 | max_util) |
| 126 | return ts | 125 | return ts |
| @@ -156,7 +155,10 @@ class Generator(object): | |||
| 156 | '''Set default parameter values and check that values are valid.''' | 155 | '''Set default parameter values and check that values are valid.''' |
| 157 | for option in self.options: | 156 | for option in self.options: |
| 158 | if option.name not in params: | 157 | if option.name not in params: |
| 159 | params[option.name] = option.default | 158 | val = option.default |
| 159 | val = val if type(val) == type([]) else [val] | ||
| 160 | |||
| 161 | params[option.name] = val | ||
| 160 | else: | 162 | else: |
| 161 | option.hidden = True | 163 | option.hidden = True |
| 162 | params[option.name] = self._check_value(option.name, | 164 | params[option.name] = self._check_value(option.name, |
diff --git a/gen/mc_generators.py b/gen/mc_generators.py index 704bcc3..8f5bd84 100644 --- a/gen/mc_generators.py +++ b/gen/mc_generators.py | |||
| @@ -1,8 +1,10 @@ | |||
| 1 | import gen.rv as rv | 1 | import gen.rv as rv |
| 2 | 2 | ||
| 3 | from color import get_cache_info,CacheInfo,BlockColorScheme,RandomColorScheme,EvilColorScheme | 3 | from color import get_cache_info,CacheInfo,BlockColorScheme,RandomColorScheme,EvilColorScheme |
| 4 | from common import try_get_config_option | 4 | from common import try_get_config_option, log_once |
| 5 | from gen.generator import GenOption,Generator,NAMED_UTILIZATIONS,NAMED_PERIODS | 5 | from gen.generator import GenOption,Generator,NAMED_UTILIZATIONS,NAMED_PERIODS |
| 6 | from parse.col_map import ColMap | ||
| 7 | from parse.tuple_table import TupleTable | ||
| 6 | 8 | ||
| 7 | 9 | ||
| 8 | NAMED_SHARES = { | 10 | NAMED_SHARES = { |
| @@ -188,24 +190,24 @@ class McGenerator(Generator): | |||
| 188 | 190 | ||
| 189 | return self._create_taskset(params, periods, utils, max_util) | 191 | return self._create_taskset(params, periods, utils, max_util) |
| 190 | 192 | ||
| 191 | def _customize(self, task_system, params): | 193 | def _get_tasks(self, params): |
| 192 | pass | 194 | return {'lvla': self.__create_lvla_sched(params), |
| 195 | 'lvlb': self.__create_lvlb_sched(params), | ||
| 196 | 'lvlc': self.__create_lvlc_sched(params)} | ||
| 193 | 197 | ||
| 194 | def _create_exp(self, params): | 198 | def _create_exp(self, params): |
| 195 | # Ugly way of doing it | 199 | # Ugly way of doing it |
| 196 | self.shares = self._create_dist('shares', params['shares'], | 200 | self.shares = self._create_dist('shares', params['shares'], |
| 197 | NAMED_SHARES) | 201 | NAMED_SHARES) |
| 198 | 202 | ||
| 199 | tasks = {'lvla': self.__create_lvla_sched(params), | 203 | tasks = self._get_tasks(params) |
| 200 | 'lvlb': self.__create_lvlb_sched(params), | ||
| 201 | 'lvlc': self.__create_lvlc_sched(params)} | ||
| 202 | 204 | ||
| 203 | conf_options = {MC_OPT : 'y'} | 205 | conf_options = {MC_OPT : 'y'} |
| 204 | if params['timer_merging']: | 206 | if params['timer_merging']: |
| 205 | conf_options[TM_OPT] = 'y' | 207 | conf_options[TM_OPT] = 'y' |
| 206 | if params['redirect']: | 208 | if params['redirect']: |
| 207 | if not params['release_master']: | 209 | if not params['release_master']: |
| 208 | print("Forcing release master option to enable redirection.") | 210 | log_once("Forcing release master option to enable redirection.") |
| 209 | params['release_master'] = 'y' | 211 | params['release_master'] = 'y' |
| 210 | conf_options[RD_OPT] = 'y' | 212 | conf_options[RD_OPT] = 'y' |
| 211 | if params['slack_stealing']: | 213 | if params['slack_stealing']: |
| @@ -241,8 +243,11 @@ TP_TYPE = """#if $type != 'unmanaged' | |||
| 241 | /proc/sys/litmus/color/preempt_cache{0} | 243 | /proc/sys/litmus/color/preempt_cache{0} |
| 242 | #end if""" | 244 | #end if""" |
| 243 | 245 | ||
| 246 | # Always add some pages | ||
| 247 | TP_ADD = """/proc/sys/litmus/color/add_pages{1}""" | ||
| 248 | |||
| 244 | # Use special spin for color tasks | 249 | # Use special spin for color tasks |
| 245 | TP_COLOR_BASE = """colorspin -y $t.id -x $t.colorcsv """ | 250 | TP_COLOR_BASE = """colorspin -y $t.id -x $t.colorcsv -q $t.wss -l $t.loops """ |
| 246 | 251 | ||
| 247 | TP_COLOR_B = TP_BASE.format("b", TP_COLOR_BASE + "-p $t.cpu ") | 252 | TP_COLOR_B = TP_BASE.format("b", TP_COLOR_BASE + "-p $t.cpu ") |
| 248 | TP_COLOR_C = TP_BASE.format("c", TP_COLOR_BASE) | 253 | TP_COLOR_C = TP_BASE.format("c", TP_COLOR_BASE) |
| @@ -255,12 +260,16 @@ TP_CHUNK = """#if $chunk_size > 0 | |||
| 255 | COLOR_TYPES = ['scheduling', 'locking', 'unmanaged'] | 260 | COLOR_TYPES = ['scheduling', 'locking', 'unmanaged'] |
| 256 | 261 | ||
| 257 | class ColorMcGenerator(McGenerator): | 262 | class ColorMcGenerator(McGenerator): |
| 263 | __SINGLE_PAGE_LOOP_MS = {'ringo': .023} | ||
| 264 | |||
| 258 | def __init__(self, params = {}): | 265 | def __init__(self, params = {}): |
| 259 | super(ColorMcGenerator, self).__init__("MC", | 266 | super(ColorMcGenerator, self).__init__("MC", |
| 260 | templates=[TP_TYPE, TP_CHUNK, TP_COLOR_B, TP_COLOR_C], | 267 | templates=[TP_ADD, TP_TYPE, TP_CHUNK, TP_COLOR_B, TP_COLOR_C], |
| 261 | options=self.__make_options(), | 268 | options=self.__make_options(), |
| 262 | params=self.__extend_params(params)) | 269 | params=self.__extend_params(params)) |
| 263 | 270 | ||
| 271 | self.tasksets = None | ||
| 272 | |||
| 264 | def __extend_params(self, params): | 273 | def __extend_params(self, params): |
| 265 | '''Add in fixed mixed-criticality parameters.''' | 274 | '''Add in fixed mixed-criticality parameters.''' |
| 266 | params['levels'] = 2 | 275 | params['levels'] = 2 |
| @@ -278,6 +287,10 @@ class ColorMcGenerator(McGenerator): | |||
| 278 | 287 | ||
| 279 | return params | 288 | return params |
| 280 | 289 | ||
| 290 | def __get_system_name(self): | ||
| 291 | import socket | ||
| 292 | return socket.gethostname().split(".")[0] | ||
| 293 | |||
| 281 | def __make_system_info(self): | 294 | def __make_system_info(self): |
| 282 | info = get_cache_info() | 295 | info = get_cache_info() |
| 283 | 296 | ||
| @@ -298,20 +311,32 @@ class ColorMcGenerator(McGenerator): | |||
| 298 | info = CacheInfo(cache, line=line, page=page, | 311 | info = CacheInfo(cache, line=line, page=page, |
| 299 | ways=ways, sets=sets, colors=colors) | 312 | ways=ways, sets=sets, colors=colors) |
| 300 | 313 | ||
| 301 | self.system = info | 314 | self.cache = info |
| 315 | |||
| 316 | hostname = self.__get_system_name() | ||
| 317 | if hostname not in self.__SINGLE_PAGE_LOOP_MS: | ||
| 318 | first_host = self.__SINGLE_PAGE_LOOP_MS.keys()[0] | ||
| 319 | log_once("hostname", "No timing info for host %s" % hostname + | ||
| 320 | ", needed to calculate work done per task. Please get the " | ||
| 321 | "timing info and add to __SINGLE_PAGE_LOOP_MS in " + | ||
| 322 | "mc_generators.py. Assuming host %s." % first_host) | ||
| 323 | hostname = first_host | ||
| 324 | self.host = hostname | ||
| 302 | 325 | ||
| 303 | def __make_options(self): | 326 | def __make_options(self): |
| 304 | self.__make_system_info() | 327 | self.__make_system_info() |
| 305 | 328 | ||
| 306 | return [GenOption('type', COLOR_TYPES, COLOR_TYPES, | 329 | return [GenOption('type', COLOR_TYPES, COLOR_TYPES, |
| 307 | 'Cache management type.'), | 330 | 'Cache management type.'), |
| 308 | GenOption('chunk_size', float, [0], 'Chunk size.'), | 331 | GenOption('host', self.__SINGLE_PAGE_LOOP_MS.keys(), self.host, |
| 309 | GenOption('ways', int, [self.system.ways], 'Ways (associativity).'), | 332 | 'System experiment will run on (for calculating work).'), |
| 310 | GenOption('colors', int, [self.system.colors], | 333 | GenOption('chunk_size_ns', float, 0, 'Chunk size. 0 = no chunking.'), |
| 334 | GenOption('ways', int, self.cache.ways, 'Ways (associativity).'), | ||
| 335 | GenOption('colors', int, self.cache.colors, | ||
| 311 | 'System colors (cache size / ways).'), | 336 | 'System colors (cache size / ways).'), |
| 312 | GenOption('page_size', int, [self.system.page], | 337 | GenOption('page_size', int, self.cache.page, |
| 313 | 'System page size.'), | 338 | 'System page size.'), |
| 314 | GenOption('wss', [float, int], [.5], | 339 | GenOption('wss', [float, int], .5, |
| 315 | 'Task working set sizes. Can be expressed as a fraction ' + | 340 | 'Task working set sizes. Can be expressed as a fraction ' + |
| 316 | 'of the cache.')] | 341 | 'of the cache.')] |
| 317 | 342 | ||
| @@ -346,14 +371,37 @@ class ColorMcGenerator(McGenerator): | |||
| 346 | for color, replicas in task.colors.iteritems(): | 371 | for color, replicas in task.colors.iteritems(): |
| 347 | f.write("%d, %d\n" % (color, replicas)) | 372 | f.write("%d, %d\n" % (color, replicas)) |
| 348 | 373 | ||
| 374 | def __get_loops(self, task, pages, system): | ||
| 375 | all_pages_loop = self.__SINGLE_PAGE_LOOP_MS[system] * pages | ||
| 376 | return int(task.cost / all_pages_loop) + 1 | ||
| 377 | |||
| 378 | def _get_tasks(self, params): | ||
| 379 | # Share tasksets amongst experiments with different types but | ||
| 380 | # identical other parameters for proper comparisons | ||
| 381 | if self.tasksets == None: | ||
| 382 | fields = params.keys() | ||
| 383 | fields.remove("type") | ||
| 384 | self.tasksets = TupleTable( ColMap(fields), lambda:None ) | ||
| 385 | |||
| 386 | if params not in self.tasksets: | ||
| 387 | ts = super(ColorMcGenerator, self)._get_tasks(params) | ||
| 388 | self.tasksets[params] = ts | ||
| 389 | |||
| 390 | return self.tasksets[params] | ||
| 391 | |||
| 349 | def _customize(self, task_system, params): | 392 | def _customize(self, task_system, params): |
| 350 | '''Add coloring properties to the mixed-criticality task system.''' | 393 | '''Add coloring properties to the mixed-criticality task system.''' |
| 394 | pages_needed = self.__get_wss_pages(params) | ||
| 395 | real_wss = params['page_size'] * pages_needed | ||
| 396 | |||
| 351 | # Every task needs a unique id for coloring and wss walk order | 397 | # Every task needs a unique id for coloring and wss walk order |
| 352 | all_tasks = [] | 398 | all_tasks = [] |
| 353 | for level, tasks in task_system.iteritems(): | 399 | for level, tasks in task_system.iteritems(): |
| 354 | all_tasks += tasks | 400 | all_tasks += tasks |
| 355 | for i, task in enumerate(all_tasks): | 401 | for i, task in enumerate(all_tasks): |
| 356 | task.id = i | 402 | task.id = i |
| 403 | task.wss = real_wss | ||
| 404 | task.loops = self.__get_loops(task, pages_needed, params['host']) | ||
| 357 | 405 | ||
| 358 | c = params['colors'] | 406 | c = params['colors'] |
| 359 | w = params['ways'] | 407 | w = params['ways'] |
| @@ -365,8 +413,6 @@ class ColorMcGenerator(McGenerator): | |||
| 365 | srt_colorer = RandomColorScheme(c, w) | 413 | srt_colorer = RandomColorScheme(c, w) |
| 366 | hrt_colorer = BlockColorScheme(c, w, way_first=True) | 414 | hrt_colorer = BlockColorScheme(c, w, way_first=True) |
| 367 | 415 | ||
| 368 | pages_needed = self.__get_wss_pages(params) | ||
| 369 | |||
| 370 | hrt_colorer.color(task_system['lvlb'], pages_needed) | 416 | hrt_colorer.color(task_system['lvlb'], pages_needed) |
| 371 | srt_colorer.color(task_system['lvlc'], pages_needed) | 417 | srt_colorer.color(task_system['lvlc'], pages_needed) |
| 372 | 418 | ||
