timfuz: min corner tweaks

Signed-off-by: John McMaster <johndmcmaster@gmail.com>
This commit is contained in:
John McMaster 2018-09-12 15:14:18 -07:00
parent 2ad0bf82fc
commit c965288e75
5 changed files with 61 additions and 23 deletions

View File

@ -33,34 +33,44 @@ def mkestimate(Anp, b):
x0[coli] = min(x0[coli], ub)
return x0
def save(outfn, res, names, corner):
def save(outfn, xvals, names, corner):
# ballpark minimum actual observed delay is around 7 (carry chain)
# anything less than one is probably a solver artifact
delta = 0.5
corneri = corner_s2i[corner]
print('Writing resutls')
# Round conservatively
roundf = {
'fast_max': math.ceil,
'fast_min': math.floor,
'slow_max': math.ceil,
'slow_min': math.floor,
}[corner]
print('Writing results')
skips = 0
keeps = 0
with open(outfn, 'w') as fout:
# write as one variable per line
# this natively forms a bound if fed into linprog solver
fout.write('ico,fast_max fast_min slow_max slow_min,rows...\n')
for xval, name in zip(res.x, names):
for xval, name in zip(xvals, names):
row_ico = 1
# FIXME: only report for the given corner?
# also review ceil vs floor choice for min vs max
# lets be more conservative for now
if xval < delta:
#print('Skipping %s: %0.6f' % (name, xval))
skips += 1
continue
keeps += 1
#xvali = round(xval)
items = [str(row_ico), acorner2csv(math.ceil(xval), corneri)]
items = [str(row_ico), acorner2csv(roundf(xval), corneri)]
items.append('%u %s' % (1, name))
fout.write(','.join(items) + '\n')
print('Wrote: skip %u => %u / %u valid delays' % (skips, len(names) - skips, len(names)))
print('Wrote: skip %u => %u / %u valid delays' % (skips, keeps, len(names)))
assert keeps, 'Failed to estimate delay'
def run_corner(Anp, b, names, corner, verbose=False, opts={}, meta={}, outfn=None):
# Given timing scores for above delays (-ps)
@ -131,7 +141,7 @@ def run_corner(Anp, b, names, corner, verbose=False, opts={}, meta={}, outfn=Non
print('Done')
if outfn:
save(outfn, res, names, corner)
save(outfn, res.x, names, corner)
def main():
import argparse
@ -148,23 +158,19 @@ def main():
parser.add_argument('--out', default=None, help='output timing delay .json')
parser.add_argument(
'fns_in',
nargs='*',
nargs='+',
help='timing3.csv input files')
args = parser.parse_args()
# Store options in dict to ease passing through functions
bench = Benchmark()
fns_in = args.fns_in
if not fns_in:
fns_in = glob.glob('specimen_*/timing3.csv')
sub_json = None
if args.sub_json:
sub_json = load_sub(args.sub_json)
try:
timfuz_solve.run(run_corner=run_corner, sub_json=sub_json,
fns_in=fns_in, corner=args.corner, massage=args.massage, outfn=args.out, verbose=args.verbose)
fns_in=args.fns_in, corner=args.corner, massage=args.massage, outfn=args.out, verbose=args.verbose)
finally:
print('Exiting after %s' % bench)

View File

@ -18,7 +18,7 @@ def save(outfn, xvals, names, corner):
delta = 0.5
corneri = corner_s2i[corner]
print('Writing resutls')
print('Writing results')
zeros = 0
with open(outfn, 'w') as fout:
# write as one variable per line

View File

@ -41,6 +41,10 @@ corner_s2i = OrderedDict([
class SimplifiedToZero(Exception):
pass
def allow_zero_eqns():
return os.getenv('ALLOW_ZERO_EQN', 'N') == 'Y'
def print_eqns(A_ubd, b_ub, verbose=0, lim=3, label=''):
rows = len(b_ub)
@ -147,6 +151,13 @@ def simplify_rows(Ads, b_ub, remove_zd=False, corner=None):
'slow_max': max,
'slow_min': min,
}[corner]
# An outlier to make unknown values be ignored
T_UNK = {
'fast_max': 0,
'fast_min': 10e9,
'slow_max': 0,
'slow_min': 10e9,
}[corner]
sys.stdout.write('SimpR ')
sys.stdout.flush()
@ -173,7 +184,7 @@ def simplify_rows(Ads, b_ub, remove_zd=False, corner=None):
continue
rowt = Ar_ds2t(rowd)
eqns[rowt] = minmax(eqns.get(rowt, 0), b)
eqns[rowt] = minmax(eqns.get(rowt, T_UNK), b)
print(' done')
if len(eqns) == 0:

View File

@ -80,8 +80,8 @@ def derive_eq_by_row(Ads, b, verbose=0, col_lim=0, tweak=False):
How to do this in a reasonable time span?
Also equations are sparse, which makes this harder to compute
'''
assert len(Ads) == len(b), 'Ads, b length mismatch'
rows = len(Ads)
assert rows == len(b)
# Index equations into hash maps so can lookup sparse elements quicker
assert len(Ads) == len(b)
@ -403,6 +403,8 @@ def massage_equations_inc_col_lim(Ads, b, verbose=False, corner=None):
Remove these columns as necessary to speed up solving
'''
assert len(Ads) == len(b), 'Ads, b length mismatch'
def debug(what):
if verbose:
print('')

View File

@ -2,7 +2,7 @@
# https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.optimize.linprog.html
from scipy.optimize import linprog
from timfuz import Benchmark, simplify_rows, loadc_Ads_b, index_names, A_ds2np, run_sub_json, print_eqns, Ads2bounds, instances, SimplifiedToZero
from timfuz import Benchmark, simplify_rows, loadc_Ads_b, index_names, A_ds2np, run_sub_json, print_eqns, Ads2bounds, instances, SimplifiedToZero, allow_zero_eqns
from timfuz_massage import massage_equations
import numpy as np
import glob
@ -68,15 +68,30 @@ def check_feasible(A_ub, b_ub):
raise Exception("Bad ")
print(' done')
def filter_bounds(Ads, b, bounds):
def filter_bounds(Ads, b, bounds, corner):
'''Given min variable delays, remove rows that won't constrain solution'''
#assert len(bounds) > 0
if 'max' in corner:
# Keep delays possibly larger than current bound
def keep(row_b, est):
return row_b > est
T_UNK = 0
elif 'min' in corner:
# Keep delays possibly smaller than current bound
def keep(row_b, est):
return row_b < est
T_UNK = 1e9
else:
assert 0
ret_Ads = []
ret_b = []
for row_ds, row_b in zip(Ads, b):
# some variables get estimated at 0
est = sum([bounds.get(k, 0) * v for k, v in row_ds.items()])
est = sum([bounds.get(k, T_UNK) * v for k, v in row_ds.items()])
# will this row potentially constrain us more?
if row_b > est:
if keep(row_b, est):
ret_Ads.append(row_ds)
ret_b.append(row_b)
return ret_Ads, ret_b
@ -114,11 +129,14 @@ def run(fns_in, corner, run_corner, sub_json=None, sub_csv=None, dedup=True, mas
if sub_csv:
Ads2, b2 = loadc_Ads_b([sub_csv], corner, ico=True)
bounds = Ads2bounds(Ads2, b2)
assert len(bounds), 'Failed to load bounds'
rows_old = len(Ads)
Ads, b = filter_bounds(Ads, b, bounds)
print('Filter bounds: %s => %s rows' % (rows_old, len(Ads)))
Ads, b = filter_bounds(Ads, b, bounds, corner)
print('Filter bounds: %s => %s + %s rows' % (rows_old, len(Ads), len(Ads2)))
Ads = Ads + Ads2
b = b + b2
assert len(Ads) or allow_zero_eqns()
assert len(Ads) == len(b), 'Ads, b length mismatch'
if verbose:
print
@ -126,6 +144,7 @@ def run(fns_in, corner, run_corner, sub_json=None, sub_csv=None, dedup=True, mas
#print
#col_dist(A_ubd, 'final', names)
print('b10', b[0:100])
'''
Given:
@ -142,7 +161,7 @@ def run(fns_in, corner, run_corner, sub_json=None, sub_csv=None, dedup=True, mas
try:
Ads, b = massage_equations(Ads, b, corner=corner)
except SimplifiedToZero:
if os.getenv('ALLOW_ZERO_EQN', 'N') != 'Y':
if not allow_zero_eqns():
raise
print('WARNING: simplified to zero equations')
Ads = []