aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2016-03-28 12:10:58 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2016-03-28 12:13:28 -0400
commit1f39b952832779cf7626afb35f720f485f4787b4 (patch)
tree0c065f7563ed04a17b07e08d0e4938c5f802ed11
parent2f0330ee24d4fa827cfd56e16bd3ae34b703a9ed (diff)
Add tools for overhead-processing workflow
-rwxr-xr-xft-combine-samples89
-rwxr-xr-xft-compute-stats135
-rwxr-xr-xft-count-samples50
-rwxr-xr-xft-extract-samples75
-rwxr-xr-xft-select-samples62
-rwxr-xr-xft-shuffle-truncate136
-rwxr-xr-xft-sort-traces48
7 files changed, 595 insertions, 0 deletions
diff --git a/ft-combine-samples b/ft-combine-samples
new file mode 100755
index 0000000..a1f19ed
--- /dev/null
+++ b/ft-combine-samples
@@ -0,0 +1,89 @@
1#!/bin/bash
2
3STRIP_CMD=""
4
5function add_strip()
6{
7 TAG=$1
8 STRIP_CMD="$STRIP_CMD -e s/_${TAG}=[^_]*//"
9}
10
11while true
12do
13 case "$1" in
14 -n | --task-count)
15 shift
16 add_strip n
17 ;;
18
19 -c | --cpu)
20 shift
21 add_strip cpu
22 ;;
23
24 -m | --msg)
25 shift
26 add_strip msg
27 ;;
28
29 -s | --seq)
30 shift
31 add_strip seq
32 ;;
33
34 -u | --util)
35 shift
36 add_strip u
37 ;;
38
39 -l | --locks)
40 shift
41 add_strip locks
42 ;;
43
44 -x | --custom)
45 shift
46 add_strip $1
47 shift
48 ;;
49
50 --std)
51 shift
52 add_strip n
53 add_strip cpu
54 add_strip msg
55 add_strip seq
56 add_strip u
57 ;;
58
59 *)
60 break
61 ;;
62 esac
63done
64
65if [ -z "$STRIP_CMD" ]
66then
67 echo "Error: no fields to strip specified."
68 exit 1
69fi
70
71function do_append() {
72 TARGET=`basename $1 | sed $STRIP_CMD`
73 TARGET="combined-$TARGET"
74 printf "\n[$NUM/$TOTAL] Combining $1 -> $TARGET\n"
75 cat $1 >> $TARGET
76}
77
78TOTAL=$#
79NUM=0
80
81echo "File names will be mangled with: sed $STRIP_CMD"
82
83
84while [ "" != "$*" ]
85do
86 NUM=$((NUM + 1))
87 do_append "$1"
88 shift
89done
diff --git a/ft-compute-stats b/ft-compute-stats
new file mode 100755
index 0000000..e07fd16
--- /dev/null
+++ b/ft-compute-stats
@@ -0,0 +1,135 @@
1#!/usr/bin/env python
2
3from __future__ import division
4
5import numpy
6
7import optparse
8import sys
9import os
10
11from os.path import splitext
12
13
14def decode_key_value_filename(name):
15 "Map key=value_otherkey=other-value names to proper dictionary."
16 params = {}
17 parts = name.split('_')
18 for p in parts:
19 kv = p.split('=')
20 k = kv[0]
21 v = kv[1] if len(kv) > 1 else None
22 params[k] = v
23 return params
24
25
26def stats_for_file(fname, scale):
27 n = 0
28 max = 0
29 p95 = 0
30 p99 = 0
31 p999 = 0
32 min = 0
33 med = 0
34 avg = 0
35 std = 0
36 var = 0
37
38 size = os.stat(fname).st_size
39 if size:
40 samples = numpy.memmap(fname, dtype='float32', mode='c')
41
42 n = len(samples)
43 if n > 0:
44 samples *= scale
45 max = numpy.amax(samples)
46 p95 = numpy.percentile(samples, 95.0)
47 p99 = numpy.percentile(samples, 99.0)
48 p999 = numpy.percentile(samples, 99.9)
49 med = numpy.median(samples)
50 avg = numpy.mean(samples)
51 min = numpy.amin(samples)
52
53 std = numpy.std(samples, ddof=1)
54 var = numpy.var(samples)
55
56 return [n, max, p999, p99, p95, avg, med, min, std, var]
57
58o = optparse.make_option
59
60opts = [
61 o('-p', '--cycles-per-usec', action='store', dest='cycles', type='float',
62 help='how many cycles per usec'),
63 ]
64
65defaults = {
66 'cycles' : None,
67 }
68
69options = None
70
71def fmt_cell(x):
72 if type(x) == str:
73 return "%25s" % x
74 if type(x) == int:
75 return "%25d" % x
76 else:
77 return "%25.5f" % x
78
79def write_header():
80 labels = ["Plugin", "#cores", "Overhead", 'Unit', "#tasks",
81 "#samples",
82 "max", "99.9th perc.", "99th perc.", "95th perc.",
83 "avg", "med", "min", "std", "var", "file"]
84 header = ", ".join(fmt_cell(x) for x in labels)
85 print '#%s' % header[1:]
86
87
88def stats_file(fname):
89 name, ext = splitext(fname)
90 conf = decode_key_value_filename(name)
91
92 if 'overhead' in conf and conf['overhead'].rfind('-LATENCY') != -1:
93 # latency is stored in nanoseconds, not cycles
94 scale = 1 / 1000 # convert from nanoseconds
95 unit = 'microseconds (scale = 1/1000)'
96 elif options.cycles is None:
97 scale = 1
98 unit = 'cycles'
99 else:
100 # convert from cycles to usec
101 scale = 1 / options.cycles
102 unit = 'microseconds (scale = 1/%f)' % options.cycles
103
104 stats = stats_for_file(fname, scale)
105 if 'locks' in conf:
106 sched = '%s_locks=%s' % (conf['scheduler'], conf['locks'])
107 elif 'scheduler' in conf:
108 sched = conf['scheduler']
109 else:
110 sched = 'UNKNOWN'
111
112 ohead = conf['overhead'] if 'overhead' in conf else 'UNKNOWN'
113 n = conf['n'] if 'n' in conf else '*'
114 m = conf['m'] if 'm' in conf else '*'
115
116 info = [sched, m, ohead, unit, n]
117 finfo = [fname]
118 print ", ".join([fmt_cell(x) for x in info + stats + finfo])
119 sys.stdout.flush()
120
121if __name__ == '__main__':
122 # FIXME: would be nicer with argparse
123 parser = optparse.OptionParser(option_list=opts)
124 parser.set_defaults(**defaults)
125 (options, files) = parser.parse_args()
126
127 try:
128 write_header()
129 for f in files: