aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-03-18 13:15:42 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2013-03-18 13:15:42 -0400
commit16dfc8df20c6befeed423217a2e0f5ae59b5a04d (patch)
tree722ff18b111f6ab2fc11fffa46e78889bd2d5708
parent652a57b5a53e41e585c7e0d10601c807ba08c36f (diff)
Use smarter defaults which can handle data from Bjorns scripts.
-rw-r--r--common.py51
-rw-r--r--config/config.py5
-rw-r--r--gen/generator.py5
-rw-r--r--parse/dir_map.py3
-rw-r--r--parse/ft.py2
-rw-r--r--parse/point.py3
-rwxr-xr-xparse_exps.py35
-rw-r--r--run/executable/executable.py2
-rw-r--r--run/litmus_util.py50
-rw-r--r--run/tracer.py10
-rwxr-xr-xrun_exps.py9
11 files changed, 92 insertions, 83 deletions
diff --git a/common.py b/common.py
index d080e1a..cba31bf 100644
--- a/common.py
+++ b/common.py
@@ -1,5 +1,6 @@
1import os 1import os
2import re 2import re
3import stat
3import subprocess 4import subprocess
4import sys 5import sys
5 6
@@ -134,3 +135,53 @@ def load_params(fname):
134 raise IOError("Invalid param file: %s\n%s" % (fname, e)) 135 raise IOError("Invalid param file: %s\n%s" % (fname, e))
135 136
136 return params 137 return params
138
139
140def num_cpus():
141 '''Return the number of CPUs in the system.'''
142
143 lnx_re = re.compile(r'^(processor|online)')
144 cpus = 0
145
146 with open('/proc/cpuinfo', 'r') as f:
147 for line in f:
148 if lnx_re.match(line):
149 cpus += 1
150 return cpus
151
152def ft_freq():
153 umachine = subprocess.check_output(["uname", "-m"])
154
155 if re.match("armv7", umachine):
156 # Arm V7s use a millisecond timer
157 freq = 1000.0
158 elif re.match("x86", umachine):
159 # X86 timer is equal to processor clock
160 reg = re.compile(r'^cpu MHz\s*:\s*(?P<FREQ>\d+)', re.M)
161 with open('/proc/cpuinfo', 'r') as f:
162 data = f.read()
163
164 match = re.search(reg, data)
165 if not match:
166 raise Exception("Cannot parse CPU frequency from x86 CPU!")
167 freq = int(match.group('FREQ'))
168 else:
169 # You're on your own
170 freq = 0
171 return freq
172
173
174def uname_matches(reg):
175 data = subprocess.check_output(["uname", "-r"])
176 return bool( re.match(reg, data) )
177
178def is_executable(fname):
179 '''Return whether the file passed in is executable'''
180 mode = os.stat(fname)[stat.ST_MODE]
181 return mode & stat.S_IXUSR and mode & stat.S_IRUSR
182
183def is_device(dev):
184 if not os.path.exists(dev):
185 return False
186 mode = os.stat(dev)[stat.ST_MODE]
187 return not (not mode & stat.S_IFCHR)
diff --git a/config/config.py b/config/config.py
index 1199278..a6edece 100644
--- a/config/config.py
+++ b/config/config.py
@@ -1,6 +1,6 @@
1from __future__ import print_function 1from __future__ import print_function
2import itertools 2import itertools
3from common import get_executable 3from common import get_executable,ft_freq
4 4
5'''Paths to binaries.''' 5'''Paths to binaries.'''
6BINS = {'rtspin' : get_executable('rtspin', 'liblitmus'), 6BINS = {'rtspin' : get_executable('rtspin', 'liblitmus'),
@@ -16,6 +16,7 @@ BINS = {'rtspin' : get_executable('rtspin', 'liblitmus'),
16 16
17'''Names of output files.''' 17'''Names of output files.'''
18FILES = {'ft_data' : 'ft.bin', 18FILES = {'ft_data' : 'ft.bin',
19 'ft_matches' : r'(ft.*\.bin)|(.*\.ft)',
19 'linux_data' : 'trace.dat', 20 'linux_data' : 'trace.dat',
20 'sched_data' : 'st-{}.bin', 21 'sched_data' : 'st-{}.bin',
21 'log_data' : 'trace.slog'} 22 'log_data' : 'trace.slog'}
@@ -34,7 +35,7 @@ DEFAULTS = {'params_file' : 'params.py',
34 'sched_file' : 'sched.py', 35 'sched_file' : 'sched.py',
35 'duration' : 10, 36 'duration' : 10,
36 'spin' : 'rtspin', 37 'spin' : 'rtspin',
37 'cycles' : 2000} 38 'cycles' : ft_freq() or 2000}
38 39
39'''Default sched_trace events (this is all of them).''' 40'''Default sched_trace events (this is all of them).'''
40SCHED_EVENTS = range(501, 513) 41SCHED_EVENTS = range(501, 513)
diff --git a/gen/generator.py b/gen/generator.py
index dbf2a7b..8c3048b 100644
--- a/gen/generator.py
+++ b/gen/generator.py
@@ -1,11 +1,10 @@
1import gen.rv as rv 1import gen.rv as rv
2import os 2import os
3import run.litmus_util as lu
4import shutil as sh 3import shutil as sh
5 4
6from Cheetah.Template import Template 5from Cheetah.Template import Template
7from collections import namedtuple 6from collections import namedtuple
8from common import get_config_option 7from common import get_config_option,num_cpus
9from config.config import DEFAULTS,PARAMS 8from config.config import DEFAULTS,PARAMS
10from gen.dp import DesignPointGenerator 9from gen.dp import DesignPointGenerator
11from parse.col_map import ColMapBuilder 10from parse.col_map import ColMapBuilder
@@ -69,7 +68,7 @@ class Generator(object):
69 if 'cpus' in params: 68 if 'cpus' in params:
70 cpus = min(map(int, params['cpus'])) 69 cpus = min(map(int, params['cpus']))
71 else: 70 else:
72 cpus = lu.num_cpus() 71 cpus = num_cpus()
73 try: 72 try:
74 config = get_config_option("RELEASE_MASTER") and True 73 config = get_config_option("RELEASE_MASTER") and True
75 except: 74 except:
diff --git a/parse/dir_map.py b/parse/dir_map.py
index 601dd3b..a8d2a83 100644
--- a/parse/dir_map.py
+++ b/parse/dir_map.py
@@ -56,6 +56,9 @@ class DirMap(object):
56 56
57 remove_childless2(self.root) 57 remove_childless2(self.root)
58 58
59 def is_empty(self):
60 return not len(self.root.children)
61
59 def write(self, out_dir): 62 def write(self, out_dir):
60 def write2(path, node): 63 def write2(path, node):
61 out_path = "/".join(path) 64 out_path = "/".join(path)
diff --git a/parse/ft.py b/parse/ft.py
index 19453d1..98405f4 100644
--- a/parse/ft.py
+++ b/parse/ft.py
@@ -63,7 +63,7 @@ def extract_ft_data(result, data_dir, work_dir, cycles):
63 data_dir = os.path.abspath(data_dir) 63 data_dir = os.path.abspath(data_dir)
64 work_dir = os.path.abspath(work_dir) 64 work_dir = os.path.abspath(work_dir)
65 65
66 freg = conf.FILES['ft_data'] + "$" 66 freg = conf.FILES['ft_matches'] + "$"
67 bins = [f for f in os.listdir(data_dir) if re.match(freg, f)] 67 bins = [f for f in os.listdir(data_dir) if re.match(freg, f)]
68 68
69 if not len(bins): 69 if not len(bins):
diff --git a/parse/point.py b/parse/point.py
index d577306..f2b266a 100644
--- a/parse/point.py
+++ b/parse/point.py
@@ -128,8 +128,7 @@ class ExpPoint(object):
128 self.stats[type] = value 128 self.stats[type] = value
129 129
130 def __str__(self): 130 def __str__(self):
131 # return "<ExpPoint-%s>\n%s" % (self.id, dict_str(self.stats)) 131 return "<ExpPoint-%s>\n%s" % (self.id, dict_str(self.stats))
132 return "<ExpPoint-%s>" % (self.id)
133 132
134 def get_stats(self): 133 def get_stats(self):
135 return self.stats.keys() 134 return self.stats.keys()
diff --git a/parse_exps.py b/parse_exps.py
index 7dfc9cd..8fcf5c3 100755
--- a/parse_exps.py
+++ b/parse_exps.py
@@ -22,8 +22,6 @@ def parse_args():
22 # TODO: convert data-dir to proper option, clean 'dest' options 22 # TODO: convert data-dir to proper option, clean 'dest' options
23 parser = OptionParser("usage: %prog [options] [data_dir]...") 23 parser = OptionParser("usage: %prog [options] [data_dir]...")
24 24
25 print("default to no params.py")
26
27 parser.add_option('-o', '--out', dest='out', 25 parser.add_option('-o', '--out', dest='out',
28 help='file or directory for data output', default='parse-data') 26 help='file or directory for data output', default='parse-data')
29 parser.add_option('-c', '--clean', action='store_true', default=False, 27 parser.add_option('-c', '--clean', action='store_true', default=False,
@@ -44,15 +42,15 @@ ExpData = namedtuple('ExpData', ['path', 'params', 'work_dir'])
44 42
45def get_exp_params(data_dir, cm_builder): 43def get_exp_params(data_dir, cm_builder):
46 param_file = "%s/%s" % (data_dir, conf.DEFAULTS['params_file']) 44 param_file = "%s/%s" % (data_dir, conf.DEFAULTS['params_file'])
47 if not os.path.isfile: 45 if os.path.isfile(param_file):
48 raise Exception("No param file '%s' exists!" % param_file) 46 params = load_params(param_file)
49
50 params = load_params(param_file)
51 47
52 # Store parameters in cm_builder, which will track which parameters change 48 # Store parameters in cm_builder, which will track which parameters change
53 # across experiments 49 # across experiments
54 for key, value in params.iteritems(): 50 for key, value in params.iteritems():
55 cm_builder.try_add(key, value) 51 cm_builder.try_add(key, value)
52 else:
53 params = {}
56 54
57 # Cycles must be present for feather-trace measurement parsing 55 # Cycles must be present for feather-trace measurement parsing
58 if conf.PARAMS['cycles'] not in params: 56 if conf.PARAMS['cycles'] not in params:
@@ -164,16 +162,25 @@ def main():
164 if opts.force and os.path.exists(opts.out): 162 if opts.force and os.path.exists(opts.out):
165 sh.rmtree(opts.out) 163 sh.rmtree(opts.out)
166 164
167 result_table = result_table.reduce() 165 reduced_table = result_table.reduce()
168 166
169 sys.stderr.write("Writing result...\n") 167 sys.stderr.write("Writing result...\n")
170 if opts.write_map: 168 if opts.write_map:
171 # Write summarized results into map 169 # Write summarized results into map
172 result_table.write_map(opts.out) 170 reduced_table.write_map(opts.out)
173 else: 171 else:
174 # Write out csv directories for all variable params 172 # Write out csv directories for all variable params
175 dir_map = result_table.to_dir_map() 173 dir_map = reduced_table.to_dir_map()
176 dir_map.write(opts.out) 174
175 # No csvs to write, assume user meant to print out data
176 if dir_map.is_empty():
177 sys.stderr.write("Too little data to make csv files.\n")
178 if not opts.verbose:
179 for key, exp in result_table:
180 for e in exp:
181 print(e)
182 else:
183 dir_map.write(opts.out)
177 184
178if __name__ == '__main__': 185if __name__ == '__main__':
179 main() 186 main()
diff --git a/run/executable/executable.py b/run/executable/executable.py
index 0a408b7..02e35ae 100644
--- a/run/executable/executable.py
+++ b/run/executable/executable.py
@@ -1,7 +1,7 @@
1import sys 1import sys
2import subprocess 2import subprocess
3import signal 3import signal
4from ..litmus_util import is_executable 4from common import is_executable
5 5
6class Executable(object): 6class Executable(object):
7 '''Parent object that represents an executable for use in task-sets.''' 7 '''Parent object that represents an executable for use in task-sets.'''
diff --git a/run/litmus_util.py b/run/litmus_util.py
index 8a7f87d..b9080c1 100644
--- a/run/litmus_util.py
+++ b/run/litmus_util.py
@@ -1,43 +1,8 @@
1import re 1import re
2import time 2import time
3import subprocess 3import subprocess
4import os
5import stat
6import config.config as conf 4import config.config as conf
7 5
8def num_cpus():
9 '''Return the number of CPUs in the system.'''
10
11 lnx_re = re.compile(r'^(processor|online)')
12 cpus = 0
13
14 with open('/proc/cpuinfo', 'r') as f:
15 for line in f:
16 if lnx_re.match(line):
17 cpus += 1
18 return cpus
19
20def ft_freq():
21 umachine = subprocess.check_output(["uname", "-m"])
22
23 if re.match("armv7", umachine):
24 # Arm V7s use a millisecond timer
25 freq = 1000.0
26 elif re.match("x86", umachine):
27 # X86 timer is equal to processor clock
28 reg = re.compile(r'^cpu MHz\s*:\s*(?P<FREQ>\d+)', re.M)
29 with open('/proc/cpuinfo', 'r') as f:
30 data = f.read()
31
32 match = re.search(reg, data)
33 if not match:
34 raise Exception("Cannot parse CPU frequency from x86 CPU!")
35 freq = int(match.group('FREQ'))
36 else:
37 # You're on your own
38 freq = 0
39 return freq
40
41def switch_scheduler(switch_to_in): 6def switch_scheduler(switch_to_in):
42 '''Switch the scheduler to whatever is passed in. 7 '''Switch the scheduler to whatever is passed in.
43 8
@@ -60,21 +25,6 @@ def switch_scheduler(switch_to_in):
60 if switch_to != cur_plugin: 25 if switch_to != cur_plugin:
61 raise Exception("Could not switch to plugin: %s" % switch_to) 26 raise Exception("Could not switch to plugin: %s" % switch_to)
62 27
63def uname_matches(reg):
64 data = subprocess.check_output(["uname", "-r"])
65 return bool( re.match(reg, data) )
66
67def is_executable(fname):
68 '''Return whether the file passed in is executable'''
69 mode = os.stat(fname)[stat.ST_MODE]
70 return mode & stat.S_IXUSR and mode & stat.S_IRUSR
71
72def is_device(dev):
73 if not os.path.exists(dev):
74 return False
75 mode = os.stat(dev)[stat.ST_MODE]
76 return not (not mode & stat.S_IFCHR)
77
78def waiting_tasks(): 28def waiting_tasks():
79 reg = re.compile(r'^ready.*?(?P<READY>\d+)$', re.M) 29 reg = re.compile(r'^ready.*?(?P<READY>\d+)$', re.M)
80 with open('/proc/litmus/stats', 'r') as f: 30 with open('/proc/litmus/stats', 'r') as f:
diff --git a/run/tracer.py b/run/tracer.py
index 303aae0..065797c 100644
--- a/run/tracer.py
+++ b/run/tracer.py
@@ -1,7 +1,7 @@
1from . import litmus_util
2import os 1import os
3import config.config as conf 2import config.config as conf
4 3
4from common import is_device,num_cpus
5from operator import methodcaller 5from operator import methodcaller
6from run.executable.ftcat import FTcat,Executable 6from run.executable.ftcat import FTcat,Executable
7 7
@@ -58,7 +58,7 @@ class LogTracer(Tracer):
58 58
59 @staticmethod 59 @staticmethod
60 def enabled(): 60 def enabled():
61 return litmus_util.is_device(LogTracer.DEVICE_STR) 61 return is_device(LogTracer.DEVICE_STR)
62 62
63 def stop_tracing(self): 63 def stop_tracing(self):
64 map(methodcaller('interrupt'), self.bins) 64 map(methodcaller('interrupt'), self.bins)
@@ -71,7 +71,7 @@ class SchedTracer(Tracer):
71 super(SchedTracer, self).__init__("Sched Trace", output_dir) 71 super(SchedTracer, self).__init__("Sched Trace", output_dir)
72 72
73 if SchedTracer.enabled(): 73 if SchedTracer.enabled():
74 for cpu in range(litmus_util.num_cpus()): 74 for cpu in range(num_cpus()):
75 # Executable will close the stdout/stderr files 75 # Executable will close the stdout/stderr files
76 stdout_f = open('%s/st-%d.bin' % (self.output_dir, cpu), 'w') 76 stdout_f = open('%s/st-%d.bin' % (self.output_dir, cpu), 'w')
77 stderr_f = open('%s/st-%d-stderr.txt' % (self.output_dir, cpu), 'w') 77 stderr_f = open('%s/st-%d-stderr.txt' % (self.output_dir, cpu), 'w')
@@ -83,7 +83,7 @@ class SchedTracer(Tracer):
83 83
84 @staticmethod 84 @staticmethod
85 def enabled(): 85 def enabled():
86 return litmus_util.is_device("%s%d" % (SchedTracer.DEVICE_STR, 0)) 86 return is_device("%s%d" % (SchedTracer.DEVICE_STR, 0))
87 87
88class OverheadTracer(Tracer): 88class OverheadTracer(Tracer):
89 DEVICE_STR = '/dev/litmus/ft_trace0' 89 DEVICE_STR = '/dev/litmus/ft_trace0'
@@ -100,7 +100,7 @@ class OverheadTracer(Tracer):
100 100
101 @staticmethod 101 @staticmethod
102 def enabled(): 102 def enabled():
103 return litmus_util.is_device(OverheadTracer.DEVICE_STR) 103 return is_device(OverheadTracer.DEVICE_STR)
104 104
105class PerfTracer(Tracer): 105class PerfTracer(Tracer):
106 def __init__(self, output_dir): 106 def __init__(self, output_dir):
diff --git a/run_exps.py b/run_exps.py
index 195d3f8..a05ff93 100755
--- a/run_exps.py
+++ b/run_exps.py
@@ -2,13 +2,12 @@
2from __future__ import print_function 2from __future__ import print_function
3 3
4import config.config as conf 4import config.config as conf
5import run.litmus_util as lu
6import os 5import os
7import re 6import re
8import shutil 7import shutil
9import traceback 8import traceback
10 9
11from common import load_params,get_executable 10from common import load_params,get_executable,uname_matches,ft_freq
12from optparse import OptionParser 11from optparse import OptionParser
13from run.executable.executable import Executable 12from run.executable.executable import Executable
14from run.experiment import Experiment,ExperimentDone 13from run.experiment import Experiment,ExperimentDone
@@ -125,7 +124,7 @@ def load_experiment(sched_file, scheduler, duration, param_file, out_dir):
125 (conf.PARAMS['dur'], duration)]) 124 (conf.PARAMS['dur'], duration)])
126 125
127 # Feather-trace clock frequency saved for accurate overhead parsing 126 # Feather-trace clock frequency saved for accurate overhead parsing
128 ft_freq = lu.ft_freq() 127 ft_freq = ft_freq()
129 if ft_freq: 128 if ft_freq:
130 out_params[conf.PARAMS['cycles']] = ft_freq 129 out_params[conf.PARAMS['cycles']] = ft_freq
131 130
@@ -146,7 +145,7 @@ def run_exp(name, schedule, scheduler, kernel, duration, work_dir, out_dir):
146 proc_entries = [] 145 proc_entries = []
147 executables = [] 146 executables = []
148 147
149 if kernel and not lu.uname_matches(kernel): 148 if kernel and not uname_matches(kernel):
150 raise InvalidKernel(kernel) 149 raise InvalidKernel(kernel)
151 150
152 # Parse values for proc entries 151 # Parse values for proc entries
@@ -178,7 +177,7 @@ def run_exp(name, schedule, scheduler, kernel, duration, work_dir, out_dir):
178 if re.match(".*spin", real_spin): 177 if re.match(".*spin", real_spin):
179 real_args = ['-w'] + real_args + [duration] 178 real_args = ['-w'] + real_args + [duration]
180 179
181 if not lu.is_executable(real_spin): 180 if not is_executable(real_spin):
182 raise OSError("Cannot run spin %s: %s" % (real_spin, name)) 181 raise OSError("Cannot run spin %s: %s" % (real_spin, name))
183 182
184 executables += [Executable(real_spin, real_args)] 183 executables += [Executable(real_spin, real_args)]