123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- #!/usr/bin/env python
- import os, sys, time, getopt, math, sniper_lib
- def max_diff(l_notsorted):
- l = sorted(l_notsorted)
- try:
- l = map(float,l)
- except ValueError, e:
- # Values are not float (string, bool): print if more than one unique value
- l = map(str,l)
- if len(set(l)) > 1:
- return (1,100,True)
- else:
- return (0.0,0.0,False)
- except TypeError, e:
- # Some values are None (missing config): definitely print
- return (0.0,0.0,True)
- islendiff = len(l_notsorted) != len(l)
- if l[0] == 0.0:
- return (l[-1] - l[0], 0.0, islendiff)
- else:
- return (l[-1] - l[0], 100*(l[-1] / float(l[0]) - 1.0), islendiff)
- def get_diffs(l):
- try:
- l = map(float,l)
- except (TypeError, ValueError), e:
- return [ _ == l[0] for _ in l[1:] ]
- if l[0] == 0:
- return [ None for _ in l[1:] ]
- else:
- return [ 100 * (_ / l[0] - 1) for _ in l[1:] ]
- def group(number):
- s = '%d' % number
- groups = []
- while s and s[-1].isdigit():
- groups.append(s[-3:])
- s = s[:-3]
- return s + ','.join(reversed(groups))
- def format_value(d):
- if (type(d) is long) or (type(d) is int):
- if len(group(d)) < 12:
- return '%12s' % group(d)
- else:
- d = float(d)
- if type(d) is float:
- if abs(d) > 1:
- e = 3 * math.floor(math.log10(abs(d) or 1.) / 3)
- return '%12s' % ('%.3f' % (d / 10**e) + '%+03d' % e)
- elif abs(d) > .01:
- return '%12.6f' % d
- else:
- return '%12.3e' % d
- d = str(d)
- if len(d) > 12:
- return '%12s' % (d[-11:]+'>')
- else:
- return '%12s' % d
- def format_percent(d):
- if d > 500:
- return '%11.2fx' % (d / 100.)
- else:
- return '%+11.1f%%' % d
- def format_diff(d):
- if d is None:
- return ' ----'
- elif d is True:
- return ' =='
- elif d is False:
- return ' !='
- else:
- return format_percent(d)
- def print_diff(parmsort = None, restype = 'results', resultdirs = [], partial = None, print_alldiffs = True, print_average = False, average_nz = True):
- jobs = []
- stats = {}
- maxkeylen = -1
- resultstoprint = []
- max_cores = 0
- keys = []
- for resultdir in resultdirs:
- res = sniper_lib.get_results(resultsdir = resultdir, partial = partial)
- stats[resultdir] = res[restype]
- jobs.append(resultdir)
- # Find all key names and maximum lenghts
- def key_map((k, v)):
- return (k, len(v) if type(v) is list else 0)
- allkeys = sum([ map(key_map, s.items()) for s in stats.values() ], [])
- keyinfo = {}
- for key, length in allkeys:
- keyinfo[key] = max(keyinfo.get(key, 0), length)
- def get_element(statkey, key, core):
- data = stats[statkey].get(key)
- if data and type(data) is list and len(data) > core:
- return data[core]
- else:
- return None
- def get_average(statkey, key):
- data = stats[statkey].get(key)
- if data and type(data) is list and len(data) > 0:
- if average_nz:
- # Find cores for which this statistic is non-zero for at least one of the results
- alldata = [ stats[_statkey][key] for _statkey in stats.keys() ]
- nonzero = map(any, zip(*alldata))
- cnt = len(filter(None, nonzero)) or 1
- else:
- cnt = len(data)
- return long(sum(data) / float(cnt))
- else:
- return None
- for key, length in sorted(keyinfo.items(), key = lambda (k, v): k.lower()):
- if length > 0:
- for core in range(1 if print_average else length):
- if print_average:
- values = [ get_average(statkey, key) for statkey in jobs ]
- else:
- values = [ get_element(statkey, key, core) for statkey in jobs ]
- if any(values):
- diff, max_percent_diff, forceprint = max_diff(values)
- diffs = get_diffs(values)
- if forceprint or diff != 0:
- maxkeylen = max(len(key), maxkeylen) # Consider this key for the maximum key character length
- resultstoprint.append((key, core, values, diff, max_percent_diff, diffs))
- max_cores = max(max_cores, core)
- else:
- diff, max_percent_diff, forceprint = max_diff(map(lambda x: x.get(key, None), stats.itervalues()))
- diffs = get_diffs([ stats[statkey].get(key, None) for statkey in jobs ])
- if forceprint or diff != 0:
- maxkeylen = max(len(key), maxkeylen) # Consider this key for the maximum key character length
- data = []
- for statkey in jobs:
- try:
- data.append(stats[statkey][key])
- except KeyError:
- data.append(None)
- resultstoprint.append((key, None, data, diff, max_percent_diff, diffs))
- # Iterate through the collected data items and print them out
- print '%*s ' % (maxkeylen+5, ''),
- for statkey in jobs:
- print '%12s' % (('%s'%statkey)[-12:]),
- if print_alldiffs:
- for statkey in jobs[1:]:
- print ' '*max(0, 11 - len(str(statkey))) + u'\u0394'.encode('utf8') + str(statkey)[-11:],
- else:
- print '%12s' % 'max-%-err',
- print '%12s' % 'max-abs-err',
- print
- if parmsort == 'abs':
- resultstoprint = sorted(resultstoprint, key = lambda x: abs(x[3]), reverse = True)
- elif parmsort == 'percent':
- resultstoprint = sorted(resultstoprint, key = lambda x: abs(x[4]), reverse = True)
- for (key, core, datalist, abs_diff, percent_diff, diffs) in resultstoprint:
- if core != None:
- if print_average:
- print '%-*s[*] =' % (maxkeylen, key),
- else:
- print '%-*s[%*u] =' % (maxkeylen, key, len(str(max_cores)), core),
- else:
- print '%-*s %s =' % (maxkeylen, key, ' '*len(str(max_cores))),
- for d in datalist:
- if d == None:
- print ' ----',
- else:
- print format_value(d),
- if print_alldiffs:
- for d in diffs:
- print format_diff(d),
- else:
- print format_percent(percent_diff),
- print '%12.3g' % abs_diff,
- print
- if __name__ == "__main__":
- parmsort = None
- restype = 'results'
- resultdirs = []
- partial = None
- print_alldiffs = True
- print_average = False
- def usage():
- print 'Usage:', sys.argv[0], '[-h|--help (help)] [--sort-abs] [--sort-percent] [--max-diff] [--average] [--config] [--partial=roi-begin:roi-end] [--] [<dir> [<dirN>]]'
- try:
- opts, args = getopt.getopt(sys.argv[1:], 'h', [ 'help', 'sort-abs', 'sort-percent', 'max-diff', 'average', 'config', 'partial=' ])
- except getopt.GetoptError, e:
- print e
- usage()
- sys.exit(1)
- for o, a in opts:
- if o == '-h' or o == '--help':
- usage()
- sys.exit(1)
- if o == '--sort-abs':
- parmsort = 'abs'
- if o == '--sort-percent':
- parmsort = 'percent'
- if o == '--max-diff':
- print_alldiffs = False
- if o == '--average':
- print_average = True
- if o == '--config':
- restype = 'config'
- if o == '--partial':
- partial = tuple(a.split(':'))[0:2]
- if args:
- for arg in args:
- if os.path.isdir(arg):
- resultdirs.append(arg)
- else:
- print 'Warning: Argument [%s] is not a results directory' % arg
- pass
- else:
- print 'At least one directory is required'
- sys.exit(1)
- with sniper_lib.OutputToLess():
- print_diff(parmsort = parmsort, restype = restype, resultdirs = resultdirs, partial = partial, print_alldiffs = print_alldiffs, print_average = print_average, average_nz = True)
|