-
Notifications
You must be signed in to change notification settings - Fork 56
/
replPolicy.py
executable file
·179 lines (143 loc) · 7.4 KB
/
replPolicy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env python3
import argparse
import os
import random
import sys
from numpy import median
from cacheLib import *
import cacheSim
import logging
log = logging.getLogger(__name__)
def getActualHits(seq, level, cacheSets, cBox, cSlice, nMeasurements=10):
nb = runCacheExperiment(level, seq, cacheSets=cacheSets, cBox=cBox, cSlice=cSlice, clearHL=True, loop=1, wbinvd=True, nMeasurements=nMeasurements, agg='med')
return int(nb['L' + str(level) + '_HIT']+0.1)
def findSmallCounterexample(policy, initSeq, level, sets, cBox, cSlice, assoc, seq, nMeasurements):
seqSplit = seq.split()
for seqPrefix in [seqSplit[:i] for i in range(assoc+1, len(seqSplit)+1)]:
seq = initSeq + ' '.join(seqPrefix)
actual = getActualHits(seq, level, sets, cBox, cSlice, nMeasurements)
sim = cacheSim.getHits(seq, cacheSim.AllPolicies[policy], assoc, sets)
print('seq:' + seq + ', actual: ' + str(actual) + ', sim: ' + str(sim))
if sim != actual:
break
for i in reversed(range(0, len(seqPrefix)-1)):
tmpPrefix = seqPrefix[:i] + seqPrefix[(i+1):]
seq = initSeq + ' '.join(tmpPrefix)
actual = getActualHits(seq, level, sets, cBox, cSlice, nMeasurements)
sim = cacheSim.getHits(seq, cacheSim.AllPolicies[policy], assoc, sets)
print('seq:' + seq + ', actual: ' + str(actual) + ', sim: ' + str(sim))
if sim != actual:
seqPrefix = tmpPrefix
return ((initSeq + ' ') if initSeq else '') + ' '.join(seqPrefix)
def getRandomSeq(n):
seq = [0]
seqAct = ['']
for _ in range(0,n):
if random.choice([True, False]):
seq.append(max(seq)+1)
seqAct.append('')
else:
seq.append(random.choice(seq))
if random.randint(0,8)==0:
seqAct.append('?')
else:
seqAct.append('?')
return ' '.join(str(s) + a for s, a in zip(seq, seqAct))
def main():
parser = argparse.ArgumentParser(description='Replacement Policies')
parser.add_argument("-level", help="Cache level (Default: 1)", type=int, default=1)
parser.add_argument("-sets", help="Cache set(s) (default: 0)", default='0')
parser.add_argument("-cBox", help="cBox (default: 0)", type=int)
parser.add_argument("-slice", help="Slice (within the cBox) (default: 0)", type=int, default=0)
parser.add_argument("-nMeasurements", help="Number of measurements", type=int, default=3)
parser.add_argument("-rep", help="Number of repetitions of each experiment (Default: 1)", type=int, default=1)
parser.add_argument("-findCtrEx", help="Tries to find a small counterexample for each policy (only available for deterministic policies)", action='store_true')
parser.add_argument("-policies", help="Comma-separated list of policies to consider (Default: all deterministic policies)")
parser.add_argument("-best", help="Find the best matching policy (Default: abort if no policy agrees with all results)", action='store_true')
parser.add_argument("-randPolicies", help="Test randomized policies", action='store_true')
parser.add_argument("-allQLRUVariants", help="Test all QLRU variants", action='store_true')
parser.add_argument("-assoc", help="Override the associativity", type=int)
parser.add_argument("-initSeq", help="Adds an initialization sequence to each sequence")
parser.add_argument("-nRandSeq", help="Number of random sequences (default: 100)", type=int, default=100)
parser.add_argument("-lRandSeq", help="Length of random sequences (default: 50)", type=int, default=50)
parser.add_argument("-logLevel", help="Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)", default='WARNING')
parser.add_argument("-output", help="Output file name", default='replPolicy.html')
args = parser.parse_args()
logging.basicConfig(stream=sys.stdout, format='%(message)s', level=logging.getLevelName(args.logLevel))
policies = sorted(cacheSim.CommonPolicies.keys())
if args.policies:
policies = args.policies.split(',')
elif args.allQLRUVariants:
policies = sorted(set(cacheSim.CommonPolicies.keys())|set(cacheSim.AllDetQLRUVariants.keys()))
elif args.randPolicies:
if args.rep > 1:
sys.exit('rep > 1 not supported for random policies')
policies = sorted(cacheSim.AllRandPolicies.keys())
if args.assoc:
assoc = args.assoc
else:
assoc = getCacheInfo(args.level).assoc
cBox = 0
if args.cBox:
cBox = args.cBox
title = cpuid.cpu_name(cpuid.CPUID()) + ', Level: ' + str(args.level) + (', CBox: ' + str(cBox) if args.cBox else '')
html = ['<html>', '<head>', '<title>' + title + '</title>', '</head>', '<body>']
html += ['<h3>' + title + '</h3>']
html += ['<table border="1" style="white-space:nowrap;">']
html += ['<tr><th>Sequence</th><th>Actual</th>']
html += ['<th>' + p.replace('_', '<br>_') + '</th>' for p in policies]
html += ['</tr>']
possiblePolicies = set(policies)
counterExamples = dict()
dists = {p: 0.0 for p in policies}
seqList = []
seqList.extend(getRandomSeq(args.lRandSeq) for _ in range(0,args.nRandSeq))
for seq in seqList:
fullSeq = ((args.initSeq + ' ') if args.initSeq else '') + seq
print(fullSeq)
html += ['<tr><td>' + fullSeq + '</td>']
actualHits = set([getActualHits(fullSeq, args.level, args.sets, cBox, args.slice, args.nMeasurements) for _ in range(0, args.rep)])
html += ['<td>' + ('{' if len(actualHits) > 1 else '') + ', '.join(map(str, sorted(actualHits))) + ('}' if len(actualHits) > 1 else '') + '</td>']
outp = ''
for p in policies:
if not args.randPolicies:
sim = cacheSim.getHits(fullSeq, cacheSim.AllPolicies[p], assoc, args.sets)
if sim not in actualHits:
possiblePolicies.discard(p)
dists[p] += 1
color = 'red'
if args.findCtrEx and not p in counterExamples:
counterExamples[p] = findSmallCounterexample(p, ((args.initSeq + ' ') if args.initSeq else ''), args.level, args.sets, cBox, args.slice,
assoc, seq, args.nMeasurements)
elif len(actualHits) > 1:
color = 'yellow'
else:
color = 'green'
else:
sim = median(sum(cacheSim.getHits(fullSeq, cacheSim.AllPolicies[p], assoc, args.sets) for _ in range(0, args.nMeasurements)))
dist = (sim - actual) ** 2
dists[p] += dist
colorR = min(255, dist)
colorG = max(0, min(255, 512 - dist))
color = 'rgb(' + str(colorR) + ',' + str(colorG) + ',0)'
html += ['<td style="background-color:' + color + ';">' + str(sim) + '</td>']
html += ['</tr>']
if not args.randPolicies and not args.best:
print('Possible policies: ' + ', '.join(possiblePolicies))
if not possiblePolicies: break
if not args.randPolicies and args.findCtrEx:
print('')
print('Counter example(s):')
for p, ctrEx in counterExamples.items():
print(' ' + p + ': ' + ctrEx)
html += ['</table>', '</body>', '</html>']
with open(args.output ,'w') as f:
f.write('\n'.join(html))
os.chown(args.output, int(os.environ['SUDO_UID']), int(os.environ['SUDO_GID']))
if not args.randPolicies and not args.best:
print('Possible policies: ' + ', '.join(possiblePolicies))
else:
for p, d in reversed(sorted(dists.items(), key=lambda d: d[1])):
print(p + ': ' + str(d))
if __name__ == "__main__":
main()