diff options
-rwxr-xr-x | pm_data_analysis/pm_data_analyzer.py | 173 | ||||
-rw-r--r-- | pm_data_analysis/pmserialize.py | 25 | ||||
-rw-r--r-- | test_get_arrays.py | 21 |
3 files changed, 198 insertions, 21 deletions
diff --git a/pm_data_analysis/pm_data_analyzer.py b/pm_data_analysis/pm_data_analyzer.py new file mode 100755 index 0000000..6862f98 --- /dev/null +++ b/pm_data_analysis/pm_data_analyzer.py | |||
@@ -0,0 +1,173 @@ | |||
1 | #!/usr/bin/env python | ||
2 | # | ||
3 | # Preemption and migration overheads analysis. | ||
4 | # Take a single-task-set-size file and generate max / avg for the valid | ||
5 | # samples for preemption and different kinds of migration | ||
6 | # | ||
7 | # Save computed valid overheads and print a file suitable for processing | ||
8 | # using gnuplot / tikz / lua | ||
9 | |||
10 | import sys | ||
11 | import numpy as np | ||
12 | |||
13 | # preemption and migration C data exchanger | ||
14 | import pm | ||
15 | import pmserialize as pms | ||
16 | |||
17 | from optparse import OptionParser | ||
18 | |||
19 | class Overhead: | ||
20 | def __init__(self): | ||
21 | self.overheads = [] | ||
22 | self.index = 0 | ||
23 | |||
24 | def __iter__(self): | ||
25 | return self | ||
26 | |||
27 | def next(self): | ||
28 | if self.index == len(self.overheads): | ||
29 | self.index = 0 | ||
30 | raise StopIteration | ||
31 | self.index += 1 | ||
32 | return self.overheads[self.index - 1] | ||
33 | |||
34 | def add(self, ovd_vector, label): | ||
35 | self.overheads.append([ovd_vector, label]) | ||
36 | |||
37 | |||
38 | class InterQuartileRange: | ||
39 | def __init__(self, low, high): | ||
40 | self.low = low | ||
41 | self.high = high | ||
42 | |||
43 | def remOutliers(self, vector): | ||
44 | # discard points etc | ||
45 | return vector | ||
46 | |||
47 | def read_valid_data(filename, coresL2, valid_ovds): | ||
48 | suff = filename.find('.raw') | ||
49 | if suff == -1: | ||
50 | print "Warning: bad suffix, I may fail in finding the right files" | ||
51 | |||
52 | nf = filename[0:suff] + '_preemption.vbin' | ||
53 | valid_ovds.add(pms.unpickl_it(nf), 'preemtion') | ||
54 | nf = filename[0:suff] + '_onchip.vbin' | ||
55 | valid_ovds.add(pms.unpickl_it(nf), 'onchip') | ||
56 | nf = filename[0:suff] + '_offchip.vbin' | ||
57 | valid_ovds.add(pms.unpickl_it(nf), 'offchip') | ||
58 | if coresL2 != 0: | ||
59 | nf = filename[0:suff] + '_l2cache.vbin' | ||
60 | valid_ovds.add(pms.unpickl_it(nf), 'l2cache') | ||
61 | |||
62 | |||
63 | def process_raw_data(filename, coresL2, coresC, valid_ovds): | ||
64 | # initialize pmmodule | ||
65 | pm.load(filename, coresL2, coresC) | ||
66 | |||
67 | ovds = Overhead() | ||
68 | |||
69 | # get overheads | ||
70 | ovds.add(pm.getPreemption(), 'preemption') | ||
71 | ovds.add(pm.getOnChipMigration(), 'onchip') | ||
72 | ovds.add(pm.getOffChipMigration(), 'offchip') | ||
73 | if coresL2 != 0: | ||
74 | ovds.add(pm.getL2Migration(), 'l2cache') | ||
75 | |||
76 | if verbose: | ||
77 | for i in ovds: | ||
78 | print i[0], i[1] | ||
79 | |||
80 | # instance the statistical analizer to remove outliers | ||
81 | sd = InterQuartileRange(25,75) | ||
82 | |||
83 | for i in ovds: | ||
84 | valid_ovds.add(sd.remOutliers(i[0]), i[1]) | ||
85 | |||
86 | # serialize valid overheads | ||
87 | for i in valid_ovds: | ||
88 | suff = filename.find('.raw') | ||
89 | if suff == -1: | ||
90 | print "Warning: ugly name for outfiles" | ||
91 | |||
92 | curf = filename[0:suff] + '_' + i[1] + '.vbin' | ||
93 | pms.pickl_it(i[0], curf) | ||
94 | |||
95 | del ovds | ||
96 | |||
97 | # tssize_char is the number of chars used to represent the tssize | ||
98 | # e.g., 050 -> tsize_char = 3 | ||
99 | def analize_data(valid_ovds, filename, tssize_char): | ||
100 | suff = filename.find('.raw') | ||
101 | if suff == -1: | ||
102 | print filename | ||
103 | print "Warning: ugly name for outfiles; check number of tasks!" | ||
104 | |||
105 | nf = filename[0:suff - tssize_char - 1] + '.csv' | ||
106 | csvf = open(nf, 'a') | ||
107 | |||
108 | # taskset size | ||
109 | pms.cvs_it(csvf, filename[suff - tssize_char:suff]) | ||
110 | |||
111 | for i in valid_ovds: | ||
112 | # overhead type | ||
113 | pms.cvs_it(csvf, i[1]) | ||
114 | # data (atm just overhead, not length) | ||
115 | vector = i[0][:,0] | ||
116 | if vector != []: | ||
117 | pms.cvs_it(csvf, "%5.5f" % np.max(vector)) | ||
118 | pms.cvs_it(csvf, "%5.5f" % np.average(vector)) | ||
119 | else: | ||
120 | pms.cvs_it(csvf, "[]") | ||
121 | pms.cvs_it(csvf, "[]") | ||
122 | |||
123 | csvf.close() | ||
124 | |||
125 | # filename-extension convention to get "pretty" output filenames | ||
126 | # .raw for raw bin data | ||
127 | # .vbin for valid overheads | ||
128 | # .csv for processed final data | ||
129 | def main(): | ||
130 | usage = "Usage: %prog [options] filename" | ||
131 | description = "FILENAME is where the .raw overhead data are. Filename \ | ||
132 | and the path to it also gives the base path and filename for the \ | ||
133 | files that contains already processed overheads and the directory \ | ||
134 | where to save the output data." | ||
135 | parser = OptionParser(usage=usage, description=description) | ||
136 | parser.add_option("-l", "--cores-per-l2", dest="coresL2", | ||
137 | action="store", type="int", default="0", | ||
138 | help="number of cores per L2 cache; " | ||
139 | "if all cores share the same L2 (i.e., no L3) set this to 0 " | ||
140 | "(default = 0)") | ||
141 | parser.add_option("-c", "--cores-per-chip", dest="coresC", | ||
142 | action="store", type="int", default="4", | ||
143 | help="number of cores per chip (default = 4)") | ||
144 | parser.add_option("-r", "--read-valid-data", dest="read_valid", | ||
145 | action="store_true", default=False, | ||
146 | help="read already processed data from file") | ||
147 | parser.add_option("-v", "--verbose", dest="verbose", | ||
148 | action="store_true", default=False, | ||
149 | help="Be verbose") | ||
150 | (options, args) = parser.parse_args() | ||
151 | if len(args) != 1: | ||
152 | parser.error("Argument missing") | ||
153 | sys.exit(-1) | ||
154 | |||
155 | valid_ovds = Overhead() | ||
156 | |||
157 | global verbose | ||
158 | if options.verbose: | ||
159 | verbose = 1 | ||
160 | else: | ||
161 | verbose = 0 | ||
162 | |||
163 | if options.read_valid: | ||
164 | read_valid_data(args[0], options.coresL2, valid_ovds) | ||
165 | else: | ||
166 | process_raw_data(args[0], options.coresL2, options.coresC, | ||
167 | valid_ovds) | ||
168 | |||
169 | analize_data(valid_ovds, args[0], 3) | ||
170 | |||
171 | if __name__ == '__main__': | ||
172 | main() | ||
173 | |||
diff --git a/pm_data_analysis/pmserialize.py b/pm_data_analysis/pmserialize.py new file mode 100644 index 0000000..14e0f3b --- /dev/null +++ b/pm_data_analysis/pmserialize.py | |||
@@ -0,0 +1,25 @@ | |||
1 | #!/usr/bin/env python | ||
2 | |||
3 | import cPickle | ||
4 | import csv | ||
5 | |||
6 | # http://en.wikipedia.org/wiki/Picolit | ||
7 | def pickl_it(vector, filename): | ||
8 | f = open(filename, 'w') | ||
9 | cPickle.dump(vector, f) | ||
10 | f.close() | ||
11 | |||
12 | def unpickl_it(filename): | ||
13 | f = open(filename, 'r') | ||
14 | vector = cPickle.load(f) | ||
15 | f.close() | ||
16 | return vector | ||
17 | |||
18 | # FIXME the one char one comma format from csv | ||
19 | # is not very "human readable" :| | ||
20 | def cvs_it(file, string): | ||
21 | wr = csv.writer(file) | ||
22 | wr.writerow(string) | ||
23 | |||
24 | def uncvs_it(file, string): | ||
25 | return None | ||
diff --git a/test_get_arrays.py b/test_get_arrays.py deleted file mode 100644 index 74af08e..0000000 --- a/test_get_arrays.py +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | #!/usr/bin/python | ||
2 | import sys, pm | ||
3 | |||
4 | args = sys.argv[1:] | ||
5 | if len(args) != 1: | ||
6 | print "Filename required" | ||
7 | sys.exit(-1) | ||
8 | |||
9 | pm.load(args[0],0,4) | ||
10 | x = pm.getPreemption() | ||
11 | y = pm.getOnChipMigration() | ||
12 | z = pm.getL2Migration() | ||
13 | w = pm.getOffChipMigration() | ||
14 | print "preemption: " | ||
15 | print x | ||
16 | print "samechip:" | ||
17 | print y | ||
18 | print "l2:" | ||
19 | print z | ||
20 | print "offchip" | ||
21 | print w | ||