sniperdiff.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #!/usr/bin/env python
  2. import os, sys, time, getopt, math, sniper_lib
  3. def max_diff(l_notsorted):
  4. l = sorted(l_notsorted)
  5. try:
  6. l = map(float,l)
  7. except ValueError, e:
  8. # Values are not float (string, bool): print if more than one unique value
  9. l = map(str,l)
  10. if len(set(l)) > 1:
  11. return (1,100,True)
  12. else:
  13. return (0.0,0.0,False)
  14. except TypeError, e:
  15. # Some values are None (missing config): definitely print
  16. return (0.0,0.0,True)
  17. islendiff = len(l_notsorted) != len(l)
  18. if l[0] == 0.0:
  19. return (l[-1] - l[0], 0.0, islendiff)
  20. else:
  21. return (l[-1] - l[0], 100*(l[-1] / float(l[0]) - 1.0), islendiff)
  22. def get_diffs(l):
  23. try:
  24. l = map(float,l)
  25. except (TypeError, ValueError), e:
  26. return [ _ == l[0] for _ in l[1:] ]
  27. if l[0] == 0:
  28. return [ None for _ in l[1:] ]
  29. else:
  30. return [ 100 * (_ / l[0] - 1) for _ in l[1:] ]
  31. def group(number):
  32. s = '%d' % number
  33. groups = []
  34. while s and s[-1].isdigit():
  35. groups.append(s[-3:])
  36. s = s[:-3]
  37. return s + ','.join(reversed(groups))
  38. def format_value(d):
  39. if (type(d) is long) or (type(d) is int):
  40. if len(group(d)) < 12:
  41. return '%12s' % group(d)
  42. else:
  43. d = float(d)
  44. if type(d) is float:
  45. if abs(d) > 1:
  46. e = 3 * math.floor(math.log10(abs(d) or 1.) / 3)
  47. return '%12s' % ('%.3f' % (d / 10**e) + '%+03d' % e)
  48. elif abs(d) > .01:
  49. return '%12.6f' % d
  50. else:
  51. return '%12.3e' % d
  52. d = str(d)
  53. if len(d) > 12:
  54. return '%12s' % (d[-11:]+'>')
  55. else:
  56. return '%12s' % d
  57. def format_percent(d):
  58. if d > 500:
  59. return '%11.2fx' % (d / 100.)
  60. else:
  61. return '%+11.1f%%' % d
  62. def format_diff(d):
  63. if d is None:
  64. return ' ----'
  65. elif d is True:
  66. return ' =='
  67. elif d is False:
  68. return ' !='
  69. else:
  70. return format_percent(d)
  71. def print_diff(parmsort = None, restype = 'results', resultdirs = [], partial = None, print_alldiffs = True, print_average = False, average_nz = True):
  72. jobs = []
  73. stats = {}
  74. maxkeylen = -1
  75. resultstoprint = []
  76. max_cores = 0
  77. keys = []
  78. for resultdir in resultdirs:
  79. res = sniper_lib.get_results(resultsdir = resultdir, partial = partial)
  80. stats[resultdir] = res[restype]
  81. jobs.append(resultdir)
  82. # Find all key names and maximum lenghts
  83. def key_map((k, v)):
  84. return (k, len(v) if type(v) is list else 0)
  85. allkeys = sum([ map(key_map, s.items()) for s in stats.values() ], [])
  86. keyinfo = {}
  87. for key, length in allkeys:
  88. keyinfo[key] = max(keyinfo.get(key, 0), length)
  89. def get_element(statkey, key, core):
  90. data = stats[statkey].get(key)
  91. if data and type(data) is list and len(data) > core:
  92. return data[core]
  93. else:
  94. return None
  95. def get_average(statkey, key):
  96. data = stats[statkey].get(key)
  97. if data and type(data) is list and len(data) > 0:
  98. if average_nz:
  99. # Find cores for which this statistic is non-zero for at least one of the results
  100. alldata = [ stats[_statkey][key] for _statkey in stats.keys() ]
  101. nonzero = map(any, zip(*alldata))
  102. cnt = len(filter(None, nonzero)) or 1
  103. else:
  104. cnt = len(data)
  105. return long(sum(data) / float(cnt))
  106. else:
  107. return None
  108. for key, length in sorted(keyinfo.items(), key = lambda (k, v): k.lower()):
  109. if length > 0:
  110. for core in range(1 if print_average else length):
  111. if print_average:
  112. values = [ get_average(statkey, key) for statkey in jobs ]
  113. else:
  114. values = [ get_element(statkey, key, core) for statkey in jobs ]
  115. if any(values):
  116. diff, max_percent_diff, forceprint = max_diff(values)
  117. diffs = get_diffs(values)
  118. if forceprint or diff != 0:
  119. maxkeylen = max(len(key), maxkeylen) # Consider this key for the maximum key character length
  120. resultstoprint.append((key, core, values, diff, max_percent_diff, diffs))
  121. max_cores = max(max_cores, core)
  122. else:
  123. diff, max_percent_diff, forceprint = max_diff(map(lambda x: x.get(key, None), stats.itervalues()))
  124. diffs = get_diffs([ stats[statkey].get(key, None) for statkey in jobs ])
  125. if forceprint or diff != 0:
  126. maxkeylen = max(len(key), maxkeylen) # Consider this key for the maximum key character length
  127. data = []
  128. for statkey in jobs:
  129. try:
  130. data.append(stats[statkey][key])
  131. except KeyError:
  132. data.append(None)
  133. resultstoprint.append((key, None, data, diff, max_percent_diff, diffs))
  134. # Iterate through the collected data items and print them out
  135. print '%*s ' % (maxkeylen+5, ''),
  136. for statkey in jobs:
  137. print '%12s' % (('%s'%statkey)[-12:]),
  138. if print_alldiffs:
  139. for statkey in jobs[1:]:
  140. print ' '*max(0, 11 - len(str(statkey))) + u'\u0394'.encode('utf8') + str(statkey)[-11:],
  141. else:
  142. print '%12s' % 'max-%-err',
  143. print '%12s' % 'max-abs-err',
  144. print
  145. if parmsort == 'abs':
  146. resultstoprint = sorted(resultstoprint, key = lambda x: abs(x[3]), reverse = True)
  147. elif parmsort == 'percent':
  148. resultstoprint = sorted(resultstoprint, key = lambda x: abs(x[4]), reverse = True)
  149. for (key, core, datalist, abs_diff, percent_diff, diffs) in resultstoprint:
  150. if core != None:
  151. if print_average:
  152. print '%-*s[*] =' % (maxkeylen, key),
  153. else:
  154. print '%-*s[%*u] =' % (maxkeylen, key, len(str(max_cores)), core),
  155. else:
  156. print '%-*s %s =' % (maxkeylen, key, ' '*len(str(max_cores))),
  157. for d in datalist:
  158. if d == None:
  159. print ' ----',
  160. else:
  161. print format_value(d),
  162. if print_alldiffs:
  163. for d in diffs:
  164. print format_diff(d),
  165. else:
  166. print format_percent(percent_diff),
  167. print '%12.3g' % abs_diff,
  168. print
  169. if __name__ == "__main__":
  170. parmsort = None
  171. restype = 'results'
  172. resultdirs = []
  173. partial = None
  174. print_alldiffs = True
  175. print_average = False
  176. def usage():
  177. print 'Usage:', sys.argv[0], '[-h|--help (help)] [--sort-abs] [--sort-percent] [--max-diff] [--average] [--config] [--partial=roi-begin:roi-end] [--] [<dir> [<dirN>]]'
  178. try:
  179. opts, args = getopt.getopt(sys.argv[1:], 'h', [ 'help', 'sort-abs', 'sort-percent', 'max-diff', 'average', 'config', 'partial=' ])
  180. except getopt.GetoptError, e:
  181. print e
  182. usage()
  183. sys.exit(1)
  184. for o, a in opts:
  185. if o == '-h' or o == '--help':
  186. usage()
  187. sys.exit(1)
  188. if o == '--sort-abs':
  189. parmsort = 'abs'
  190. if o == '--sort-percent':
  191. parmsort = 'percent'
  192. if o == '--max-diff':
  193. print_alldiffs = False
  194. if o == '--average':
  195. print_average = True
  196. if o == '--config':
  197. restype = 'config'
  198. if o == '--partial':
  199. partial = tuple(a.split(':'))[0:2]
  200. if args:
  201. for arg in args:
  202. if os.path.isdir(arg):
  203. resultdirs.append(arg)
  204. else:
  205. print 'Warning: Argument [%s] is not a results directory' % arg
  206. pass
  207. else:
  208. print 'At least one directory is required'
  209. sys.exit(1)
  210. with sniper_lib.OutputToLess():
  211. print_diff(parmsort = parmsort, restype = restype, resultdirs = resultdirs, partial = partial, print_alldiffs = print_alldiffs, print_average = print_average, average_nz = True)