aboutsummaryrefslogtreecommitdiffstats
path: root/gen/color.py
diff options
context:
space:
mode:
Diffstat (limited to 'gen/color.py')
-rw-r--r--gen/color.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/gen/color.py b/gen/color.py
new file mode 100644
index 0000000..8184b8b
--- /dev/null
+++ b/gen/color.py
@@ -0,0 +1,102 @@
1import os
2import re
3
4from collections import namedtuple,defaultdict
5from math import ceil
6from random import randint
7
8class ColorScheme(object):
9 def __init__(self, colors, ways):
10 self.colors = colors
11 self.ways = ways
12
13 def color(self, tasks, wss):
14 '''Assign a color->replicas dict to each task in tasks.'''
15 raise NotImplementedError
16
17class BlockColorScheme(ColorScheme):
18 def __init__(self, colors, ways, way_first):
19 super(BlockColorScheme, self).__init__(colors, ways)
20 self.way_first = way_first
21
22 def color(self, tasks, pages_needed):
23 '''Pages are assigned in blocks, either maximizing the number of ways
24 or maximizing the number of colors used.'''
25 cpus = defaultdict(list)
26 for t in tasks:
27 cpus[t.cpu].append(t)
28
29 if self.way_first:
30 # Way first means maximize ways
31 pages_per_color = min(self.ways, pages_needed)
32 colors_per_task = int(ceil(pages_needed/pages_per_color))
33 else:
34 # Color first means maximize colors
35 colors_per_task = min(self.colors, pages_needed)
36 pages_per_color = int(ceil(pages_needed/colors_per_task))
37
38 curr_color = 0
39 for cpu, tasks in cpus.iteritems():
40 # All tasks on a CPU have the same coloring scheme
41 cpu_colors = defaultdict(int)
42 for _ in xrange(colors_per_task):
43 curr_color = (curr_color + 1) % self.colors
44 cpu_colors[curr_color] = pages_per_color
45
46 for t in tasks:
47 t.colors = cpu_colors
48
49class RandomColorScheme(ColorScheme):
50 def color(self, tasks, pages_needed):
51 '''Pages are placed randomly in the cache'''
52 if pages_needed >= self.ways * self.colors:
53 raise Exception("Too many pages: %d > %d * %d" %
54 (pages_needed, self.ways, self.colors))
55
56 for t in tasks:
57 t.colors = defaultdict(int)
58
59 for _ in xrange(pages_needed):
60 # Find the next color with available ways
61 while True:
62 next_color = randint(0, self.colors - 1)
63 if t.colors[next_color] != self.ways:
64 break
65
66 t.colors[next_color] += 1;
67
68class EvilColorScheme(ColorScheme):
69 def color(self, tasks, pages_needed):
70 '''All tasks' working sets are placed at the front of the cache'''
71 colors = defaultdict(int)
72 color = 0
73
74 while pages_needed > 0:
75 colors[color] = min(self.ways, pages_needed)
76 pages_needed -= colors[color]
77
78 color += 1
79
80 for t in tasks:
81 t.colors = colors
82
83
84INFO_FIELDS = ['cache', 'line', 'page', 'ways', 'sets', 'colors']
85INFO_PROC = '/proc/sys/litmus/color/cache_info'
86
87# Build parsing regex
88FIELD_REGEX = r"(?:.*?{0}.*?(?P<{0}>\d+).*?)"
89INFO_REGEX = "|".join([FIELD_REGEX.format(field) for field in INFO_FIELDS])
90INFO_REGEX = r"(?:{})*".format(INFO_REGEX)
91
92# To fill up this
93CacheInfo = namedtuple('CacheInfo', INFO_FIELDS)
94
95def get_cache_info():
96 if os.path.exists(INFO_PROC):
97 with open(INFO_PROC, 'r') as f:
98 data = f.read()
99 values = re.search(INFO_REGEX, data, re.M|re.I|re.S).groupdict()
100 return CacheInfo(**values)
101 else:
102 return None