diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-04-08 15:42:16 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-04-08 15:42:16 -0400 |
| commit | d169debf732270c9571be6ea6e7d920345bffc33 (patch) | |
| tree | d86c1ff5d0e4a116fcc916717abb29a026862c74 | |
| parent | 8864a4018c9b9088f330c3ef24ed7b5313ec36a2 (diff) | |
Added parameter file options for tracers and pre/post experiment commands.
| -rw-r--r-- | common.py | 2 | ||||
| -rw-r--r-- | config/config.py | 5 | ||||
| -rw-r--r-- | run/experiment.py | 56 | ||||
| -rw-r--r-- | run/tracer.py | 52 | ||||
| -rwxr-xr-x | run_exps.py | 242 |
5 files changed, 230 insertions, 127 deletions
| @@ -7,7 +7,7 @@ import sys | |||
| 7 | from collections import defaultdict | 7 | from collections import defaultdict |
| 8 | from textwrap import dedent | 8 | from textwrap import dedent |
| 9 | 9 | ||
| 10 | def get_executable(prog, hint, optional=False): | 10 | def get_executable(prog, hint='unknown', optional=False): |
| 11 | '''Search for @prog in system PATH. Print @hint if no binary is found.''' | 11 | '''Search for @prog in system PATH. Print @hint if no binary is found.''' |
| 12 | 12 | ||
| 13 | def is_exe(fpath): | 13 | def is_exe(fpath): |
diff --git a/config/config.py b/config/config.py index 49fd234..3486a40 100644 --- a/config/config.py +++ b/config/config.py | |||
| @@ -28,7 +28,10 @@ PARAMS = {'sched' : 'scheduler', # Scheduler used by run_exps | |||
| 28 | 'copts' : 'config-options', # Required kernel configuration options | 28 | 'copts' : 'config-options', # Required kernel configuration options |
| 29 | 'cycles' : 'clock-frequency', # Frequency run_exps was run with | 29 | 'cycles' : 'clock-frequency', # Frequency run_exps was run with |
| 30 | 'tasks' : 'tasks', # Number of tasks | 30 | 'tasks' : 'tasks', # Number of tasks |
| 31 | 'trial' : 'trial' # For multiple exps with same config | 31 | 'trial' : 'trial', # For multiple exps with same config |
| 32 | 'pre' : 'pre-experiment', # Run before each experiment | ||
| 33 | 'post' : 'post-experiment', # Run after each experiment | ||
| 34 | 'trace' : 'tracers' # Tracers to run with an experiment | ||
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | '''Default values for program options.''' | 37 | '''Default values for program options.''' |
diff --git a/run/experiment.py b/run/experiment.py index 03d6ab6..3dd4866 100644 --- a/run/experiment.py +++ b/run/experiment.py | |||
| @@ -3,7 +3,6 @@ import time | |||
| 3 | import run.litmus_util as lu | 3 | import run.litmus_util as lu |
| 4 | import shutil as sh | 4 | import shutil as sh |
| 5 | from operator import methodcaller | 5 | from operator import methodcaller |
| 6 | from run.tracer import SchedTracer, LogTracer, PerfTracer, LinuxTracer, OverheadTracer | ||
| 7 | 6 | ||
| 8 | class ExperimentException(Exception): | 7 | class ExperimentException(Exception): |
| 9 | '''Used to indicate when there are problems with an experiment.''' | 8 | '''Used to indicate when there are problems with an experiment.''' |
| @@ -32,7 +31,8 @@ class Experiment(object): | |||
| 32 | '''Execute one task-set and save the results. Experiments have unique IDs.''' | 31 | '''Execute one task-set and save the results. Experiments have unique IDs.''' |
| 33 | INTERRUPTED_DIR = ".interrupted" | 32 | INTERRUPTED_DIR = ".interrupted" |
| 34 | 33 | ||
| 35 | def __init__(self, name, scheduler, working_dir, finished_dir, proc_entries, executables): | 34 | def __init__(self, name, scheduler, working_dir, finished_dir, |
| 35 | proc_entries, executables, tracer_types): | ||
| 36 | '''Run an experiment, optionally wrapped in tracing.''' | 36 | '''Run an experiment, optionally wrapped in tracing.''' |
| 37 | 37 | ||
| 38 | self.name = name | 38 | self.name = name |
| @@ -46,27 +46,17 @@ class Experiment(object): | |||
| 46 | 46 | ||
| 47 | self.__make_dirs() | 47 | self.__make_dirs() |
| 48 | self.__assign_executable_cwds() | 48 | self.__assign_executable_cwds() |
| 49 | self.__setup_tracers(tracer_types) | ||
| 49 | 50 | ||
| 50 | self.tracers = [] | 51 | |
| 51 | if SchedTracer.enabled(): | 52 | def __setup_tracers(self, tracer_types): |
| 52 | self.log("Enabling sched_trace") | 53 | tracers = [ t(self.working_dir) for t in tracer_types ] |
| 53 | self.tracers.append( SchedTracer(working_dir) ) | 54 | |
| 54 | if LinuxTracer.enabled(): | 55 | self.regular_tracers = [t for t in tracers if not t.is_exact()] |
| 55 | self.log("Enabling trace-cmd") | 56 | self.exact_tracers = [t for t in tracers if t.is_exact()] |
| 56 | self.tracers.append( LinuxTracer(working_dir) ) | 57 | |
| 57 | if LogTracer.enabled(): | 58 | for t in tracers: |
| 58 | self.log("Enabling logging") | 59 | self.log("Enabling %s" % t.get_name()) |
| 59 | self.tracers.append( LogTracer(working_dir) ) | ||
| 60 | if PerfTracer.enabled(): | ||
| 61 | self.log("Tracking CPU performance counters") | ||
| 62 | self.tracers.append( PerfTracer(working_dir) ) | ||
| 63 | |||
| 64 | # Overhead trace must be handled seperately, see __run_tasks | ||
| 65 | if OverheadTracer.enabled(): | ||
| 66 | self.log("Enabling overhead tracing") | ||
| 67 | self.overhead_trace = OverheadTracer(working_dir) | ||
| 68 | else: | ||
| 69 | self.overhead_trace = None | ||
| 70 | 60 | ||
| 71 | def __make_dirs(self): | 61 | def __make_dirs(self): |
| 72 | interrupted = None | 62 | interrupted = None |
| @@ -111,11 +101,10 @@ class Experiment(object): | |||
| 111 | raise Exception("Too much time has passed waiting for tasks!") | 101 | raise Exception("Too much time has passed waiting for tasks!") |
| 112 | time.sleep(1) | 102 | time.sleep(1) |
| 113 | 103 | ||
| 114 | # Overhead tracer must be started right after release or overhead | 104 | # Exact tracers (like overheads) must be started right after release or |
| 115 | # measurements will be full of irrelevant records | 105 | # measurements will be full of irrelevant records |
| 116 | if self.overhead_trace: | 106 | self.log("Starting %d released tracers" % len(self.exact_tracers)) |
| 117 | self.log("Starting overhead trace") | 107 | map(methodcaller('start_tracing'), self.exact_tracers) |
| 118 | self.overhead_trace.start_tracing() | ||
| 119 | 108 | ||
| 120 | self.log("Releasing %d tasks" % len(self.executables)) | 109 | self.log("Releasing %d tasks" % len(self.executables)) |
| 121 | released = lu.release_tasks() | 110 | released = lu.release_tasks() |
| @@ -145,10 +134,9 @@ class Experiment(object): | |||
| 145 | if not e.wait(): | 134 | if not e.wait(): |
| 146 | ret = False | 135 | ret = False |
| 147 | 136 | ||
| 148 | # And it must be stopped here for the same reason | 137 | # And these must be stopped here for the same reason |
| 149 | if self.overhead_trace: | 138 | self.log("Stopping exact tracers") |
| 150 | self.log("Stopping overhead trace") | 139 | map(methodcaller('stop_tracing'), self.exact_tracers) |
| 151 | self.overhead_trace.stop_tracing() | ||
| 152 | 140 | ||
| 153 | if not ret: | 141 | if not ret: |
| 154 | raise ExperimentFailed(self.name) | 142 | raise ExperimentFailed(self.name) |
| @@ -186,8 +174,8 @@ class Experiment(object): | |||
| 186 | self.log("Switching to %s" % self.scheduler) | 174 | self.log("Switching to %s" % self.scheduler) |
| 187 | lu.switch_scheduler(self.scheduler) | 175 | lu.switch_scheduler(self.scheduler) |
| 188 | 176 | ||
| 189 | self.log("Starting %d tracers" % len(self.tracers)) | 177 | self.log("Starting %d regular tracers" % len(self.regular_tracers)) |
| 190 | map(methodcaller('start_tracing'), self.tracers) | 178 | map(methodcaller('start_tracing'), self.regular_tracers) |
| 191 | 179 | ||
| 192 | self.exec_out = open('%s/exec-out.txt' % self.working_dir, 'w') | 180 | self.exec_out = open('%s/exec-out.txt' % self.working_dir, 'w') |
| 193 | self.exec_err = open('%s/exec-err.txt' % self.working_dir, 'w') | 181 | self.exec_err = open('%s/exec-err.txt' % self.working_dir, 'w') |
| @@ -200,6 +188,6 @@ class Experiment(object): | |||
| 200 | self.exec_out and self.exec_out.close() | 188 | self.exec_out and self.exec_out.close() |
| 201 | self.exec_err and self.exec_err.close() | 189 | self.exec_err and self.exec_err.close() |
| 202 | 190 | ||
| 203 | self.log("Stopping tracers") | 191 | self.log("Stopping regular tracers") |
| 204 | map(methodcaller('stop_tracing'), self.tracers) | 192 | map(methodcaller('stop_tracing'), self.regular_tracers) |
| 205 | 193 | ||
diff --git a/run/tracer.py b/run/tracer.py index 065797c..6e1d05c 100644 --- a/run/tracer.py +++ b/run/tracer.py | |||
| @@ -6,10 +6,17 @@ from operator import methodcaller | |||
| 6 | from run.executable.ftcat import FTcat,Executable | 6 | from run.executable.ftcat import FTcat,Executable |
| 7 | 7 | ||
| 8 | class Tracer(object): | 8 | class Tracer(object): |
| 9 | def __init__(self, name, output_dir): | 9 | def __init__(self, name, output_dir, exact=False): |
| 10 | self.name = name | 10 | self.name = name |
| 11 | self.output_dir = output_dir | 11 | self.output_dir = output_dir |
| 12 | self.bins = [] | 12 | self.bins = [] |
| 13 | self.exact=exact | ||
| 14 | |||
| 15 | def get_name(self): | ||
| 16 | return self.name | ||
| 17 | |||
| 18 | def is_exact(self): | ||
| 19 | return self.exact | ||
| 13 | 20 | ||
| 14 | def start_tracing(self): | 21 | def start_tracing(self): |
| 15 | map(methodcaller("execute"), self.bins) | 22 | map(methodcaller("execute"), self.bins) |
| @@ -23,7 +30,7 @@ class LinuxTracer(Tracer): | |||
| 23 | LITMUS_EVENTS = "%s/events/litmus" % EVENT_ROOT | 30 | LITMUS_EVENTS = "%s/events/litmus" % EVENT_ROOT |
| 24 | 31 | ||
| 25 | def __init__(self, output_dir): | 32 | def __init__(self, output_dir): |
| 26 | super(LinuxTracer, self).__init__("trace-cmd", output_dir) | 33 | super(LinuxTracer, self).__init__("Trace-cmd / Kernelshark", output_dir) |
| 27 | 34 | ||
| 28 | extra_args = ["record", # "-e", "sched:sched_switch", | 35 | extra_args = ["record", # "-e", "sched:sched_switch", |
| 29 | "-e", "litmus:*", | 36 | "-e", "litmus:*", |
| @@ -89,7 +96,7 @@ class OverheadTracer(Tracer): | |||
| 89 | DEVICE_STR = '/dev/litmus/ft_trace0' | 96 | DEVICE_STR = '/dev/litmus/ft_trace0' |
| 90 | 97 | ||
| 91 | def __init__(self, output_dir): | 98 | def __init__(self, output_dir): |
| 92 | super(OverheadTracer, self).__init__("Overhead Trace", output_dir) | 99 | super(OverheadTracer, self).__init__("Overhead Trace", output_dir, True) |
| 93 | 100 | ||
| 94 | stdout_f = open('{0}/{1}'.format(self.output_dir, conf.FILES['ft_data']), 'w') | 101 | stdout_f = open('{0}/{1}'.format(self.output_dir, conf.FILES['ft_data']), 'w') |
| 95 | stderr_f = open('{0}/{1}.stderr.txt'.format(self.output_dir, conf.FILES['ft_data']), 'w') | 102 | stderr_f = open('{0}/{1}.stderr.txt'.format(self.output_dir, conf.FILES['ft_data']), 'w') |
| @@ -109,3 +116,42 @@ class PerfTracer(Tracer): | |||
| 109 | @staticmethod | 116 | @staticmethod |
| 110 | def enabled(): | 117 | def enabled(): |
| 111 | return False | 118 | return False |
| 119 | |||
| 120 | |||
| 121 | tracers = {} | ||
| 122 | |||
| 123 | def register_tracer(tracer, name): | ||
| 124 | tracers[name] = tracer | ||
| 125 | |||
| 126 | def get_tracer_types(names): | ||
| 127 | error = True # Error if name is not present | ||
