cpistack.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #!/usr/bin/env python
  2. # -*- coding: utf8 -*-
  3. import os, sys, re, collections, gnuplot, getopt
  4. import cpistack_data, cpistack_items, cpistack_results
  5. try:
  6. collections.defaultdict()
  7. except AttributeError, e:
  8. print sys.argv[0], "Error: This script requires Python version 2.5 or greater"
  9. sys.exit()
  10. # New-style function returning CPI stack results
  11. def cpistack_compute(jobid = 0, resultsdir = None, config = None, stats = None, data = None, partial = None,
  12. cores_list = None, core_mincomp = 0., aggregate = False,
  13. items = None, groups = None, use_simple = False, use_simple_mem = True,
  14. no_collapse = False):
  15. # Get the data
  16. cpidata = cpistack_data.CpiData(jobid = jobid, resultsdir = resultsdir, config = config, stats = stats, data = data, partial = partial)
  17. cpidata.filter(cores_list = cores_list, core_mincomp = core_mincomp)
  18. if aggregate:
  19. cpidata.aggregate()
  20. # Build the structure descriptor
  21. cpiitems = cpistack_items.CpiItems(items = items, groups = groups, use_simple = use_simple, use_simple_mem = use_simple_mem)
  22. # Group data according to descriptor
  23. results = cpistack_results.CpiResults(cpidata, cpiitems, no_collapse = no_collapse)
  24. return results
  25. def output_cpistack_text(results):
  26. print ' CPI Time'
  27. cpi = results.get_data('cpi')
  28. time = results.get_data('time')
  29. for core in results.cores:
  30. if len(results.cores) > 1:
  31. print 'Core', core
  32. total = { 'cpi': 0, 'time': 0 }
  33. for label in results.labels:
  34. print ' %-15s %6.2f %6.2f%%' % (label, cpi[core][label], 100 * time[core][label])
  35. total['cpi'] += cpi[core][label]
  36. total['time'] += time[core][label]
  37. print
  38. print ' %-15s %6.2f %6.2f%%' % ('total', total['cpi'], 100 * total['time'])
  39. def output_cpistack_table(results, metric = 'cpi'):
  40. data = results.get_data(metric)
  41. total = [ 0 for core in results.cores ]
  42. multiplier = 1.
  43. if metric == 'time':
  44. format = lambda v: '%7.2f%%' % (100 * v)
  45. title = 'Time (%)'
  46. elif metric == 'abstime':
  47. format = lambda v: '%8.2f' % v
  48. prefixes = ['', 'm', 'µ', 'n']
  49. scaleidx = 0
  50. totaltime = sum(data[0].values())
  51. while totaltime < 100. and scaleidx < len(prefixes)-1:
  52. scaleidx += 1
  53. totaltime *= 1000
  54. title = 'Time (%ss)' % prefixes[scaleidx]
  55. multiplier = 1000. ** scaleidx
  56. elif metric == 'cpi':
  57. format = lambda v: '%8.2f' % v
  58. title = 'CPI'
  59. else:
  60. raise ValueError('Unknown metric %s' % metric)
  61. print '%-20s' % title, ' '.join([ '%-9s' % ('Core %d' % core) for core in results.cores ])
  62. for label in results.labels:
  63. print '%-15s ' % label,
  64. for core in results.cores:
  65. print ' ', format(multiplier * data[core][label]),
  66. total[core] += data[core][label]
  67. print
  68. print
  69. print '%-15s ' % 'total',
  70. for core in results.cores:
  71. print ' ', format(multiplier * total[core]),
  72. print
  73. def output_cpistack_gnuplot(results, metric = 'time', outputfile = 'cpi-stack', outputdir = '.', title = '', size = (640, 480), save_gnuplot_input = False):
  74. # Use Gnuplot to make stacked bargraphs of these cpi-stacks
  75. plot_data = results.get_data(metric)
  76. colors = results.get_colors()
  77. plot_labels_with_color = [ (label, 'rgb "#%02x%02x%02x"' % colors[label]) for label in results.labels ]
  78. gnuplot.make_stacked_bargraph(os.path.join(outputdir, outputfile), plot_labels_with_color, plot_data, size = size, title = title,
  79. ylabel = metric == 'cpi' and 'Cycles per instruction' or (metric == 'abstime' and 'Time (seconds)' or 'Fraction of time'), save_gnuplot_input = save_gnuplot_input)
  80. # Legacy cpistack.cpistack() function, does most of the old one as not to break most of the scripts in papers/
  81. def cpistack(jobid = 0, resultsdir = '.', data = None, partial = None, outputfile = 'cpi-stack', outputdir = '.',
  82. use_cpi = False, use_abstime = False, use_roi = True,
  83. use_simple = False, use_simple_mem = True, no_collapse = False,
  84. gen_text_stack = True, gen_plot_stack = True, gen_csv_stack = False, csv_print_header = False,
  85. job_name = '', title = '', threads = None, threads_mincomp = .5, return_data = False, aggregate = False,
  86. size = (640, 480)):
  87. if gen_csv_stack or csv_print_header or return_data:
  88. # Not all functionality has been forward-ported, preferably use cpistack_compute instead
  89. raise NotImplementedError
  90. results = cpistack_compute(jobid = jobid, resultsdir = resultsdir, data = data, partial = partial, aggregate = aggregate,
  91. cores_list = threads, core_mincomp = threads_mincomp,
  92. groups = use_simple and cpistack_items.build_grouplist(legacy = True) or None,
  93. use_simple = use_simple, use_simple_mem = use_simple_mem, no_collapse = no_collapse)
  94. if gen_text_stack:
  95. output_cpistack_text(results)
  96. if gen_plot_stack:
  97. metric = 'cpi' if use_cpi else ('abstime' if use_abstime else 'time')
  98. output_cpistack_gnuplot(results = results, metric = metric, outputfile = os.path.join(outputdir, outputfile), title = title, size = size)
  99. if __name__ == '__main__':
  100. def usage():
  101. print 'Usage:', sys.argv[0], '[-h|--help (help)] [-j <jobid> | -d <resultsdir (default: .)>] [-o <output-filename (cpi-stack)>] [--title=""] [--without-roi] [--simplified] [--no-collapse] [--no-simple-mem] [--time|--cpi|--abstime (default: time)] [--aggregate]'
  102. jobid = 0
  103. resultsdir = '.'
  104. partial = None
  105. outputfile = 'cpi-stack'
  106. title = ''
  107. metric = None
  108. use_simple = False
  109. use_simple_mem = True
  110. no_collapse = False
  111. aggregate = False
  112. save_gnuplot_input = False
  113. try:
  114. opts, args = getopt.getopt(sys.argv[1:], "hj:d:o:", [ "help", "title=", "no-roi", "simplified", "no-collapse", "no-simple-mem", "cpi", "time", "abstime", "aggregate", "partial=", "save-gnuplot-input" ])
  115. except getopt.GetoptError, e:
  116. print e
  117. usage()
  118. sys.exit()
  119. for o, a in opts:
  120. if o == '-h' or o == '--help':
  121. usage()
  122. sys.exit()
  123. if o == '-d':
  124. resultsdir = a
  125. if o == '-j':
  126. jobid = long(a)
  127. if o == '-o':
  128. outputfile = a
  129. if o == '--title':
  130. title = a
  131. if o == '--no-roi':
  132. partial = ('start', 'stop')
  133. if o == '--simplified':
  134. use_simple = True
  135. if o == '--no-collapse':
  136. no_collapse = True
  137. if o == '--no-simple-mem':
  138. use_simple_mem = False
  139. if o == '--time':
  140. metric = 'time'
  141. if o == '--cpi':
  142. metric = 'cpi'
  143. if o == '--abstime':
  144. metric = 'abstime'
  145. if o == '--aggregate':
  146. aggregate = True
  147. if o == '--partial':
  148. if ':' not in a:
  149. sys.stderr.write('--partial=<from>:<to>\n')
  150. usage()
  151. partial = a.split(':')
  152. if o == '--save-gnuplot-input':
  153. save_gnuplot_input = True
  154. if args:
  155. usage()
  156. sys.exit(-1)
  157. results = cpistack_compute(jobid = jobid, resultsdir = resultsdir, partial = partial, aggregate = aggregate,
  158. groups = use_simple and cpistack_items.build_grouplist(legacy = True) or None,
  159. use_simple = use_simple, use_simple_mem = use_simple_mem, no_collapse = no_collapse)
  160. if len(results.cores) > 1:
  161. output_cpistack_table(results, metric = metric or 'cpi')
  162. else:
  163. output_cpistack_text(results)
  164. output_cpistack_gnuplot(results = results, metric = metric or 'time', outputfile = outputfile, title = title, save_gnuplot_input = save_gnuplot_input)