cpistack_items.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import collections, buildstack, colorsys
  2. def build_itemlist(use_simple_sync = False, use_simple_mem = True):
  3. # List of all CPI contributors: <title>, <threshold (%)>, <contributors>
  4. # <contributors> can be string: key name in sim.stats (sans "roi-end.*[<corenum>].cpi")
  5. # list : recursive list of sub-contributors
  6. # tuple : list of key names that are summed anonymously
  7. items = [
  8. [ 'base', .01, 'Base' ],
  9. [ 'dispatch_width', .01, 'Issue' ],
  10. [ 'rs_full', .01, 'RSFull' ],
  11. [ 'depend', .01, [
  12. [ 'int', .01, 'PathInt' ],
  13. [ 'fp', .01, 'PathFP' ],
  14. [ 'branch', .01, 'PathBranch' ],
  15. ] ],
  16. [ 'issue', .01, [
  17. [ 'port0', .01, 'PathP0' ],
  18. [ 'port1', .01, 'PathP1' ],
  19. [ 'port2', .01, 'PathP2' ],
  20. [ 'port34', .01, 'PathP34' ],
  21. [ 'port5', .01, 'PathP5' ],
  22. [ 'port05', .01, 'PathP05' ],
  23. [ 'port015', .01, 'PathP015' ],
  24. ] ],
  25. [ 'serial', .01, ('Serialization', 'LongLatency') ], # FIXME: can LongLatency be anything other than MFENCE?
  26. [ 'smt', .01, 'SMT' ],
  27. [ 'branch', .01, 'BranchPredictor' ],
  28. [ 'itlb', .01, 'ITLBMiss' ],
  29. [ 'dtlb', .01, 'DTLBMiss' ],
  30. [ 'ifetch', .01, (
  31. 'DataCacheL1I', 'InstructionCacheL1I', 'InstructionCacheL1', 'InstructionCacheL1_S',
  32. 'InstructionCacheL2', 'InstructionCacheL2_S', 'InstructionCacheL3', 'InstructionCacheL3_S',
  33. 'InstructionCacheL4', 'InstructionCacheL4_S', 'InstructionCachemiss', 'InstructionCache????',
  34. 'InstructionCachenuca-cache', 'InstructionCachedram-cache', 'InstructionCachedram',
  35. 'InstructionCachedram-remote', 'InstructionCachecache-remote', 'InstructionCachedram-local',
  36. 'InstructionCachepredicate-false', 'InstructionCacheprefetch-no-mapping', 'InstructionCacheunknown') ],
  37. ]
  38. if use_simple_mem:
  39. items += [
  40. [ 'mem', .01, [
  41. [ 'l1d', .01, ('DataCacheL1', 'DataCacheL1_S', 'PathLoadX', 'PathStore') ],
  42. [ 'l2', .01, ('DataCacheL2', 'DataCacheL2_S') ],
  43. [ 'l3', .01, ('DataCacheL3', 'DataCacheL3_S') ],
  44. [ 'l4', .01, ('DataCacheL4', 'DataCacheL4_S') ],
  45. [ 'remote', .01, 'DataCachecache-remote' ],
  46. [ 'nuca', .01, 'DataCachenuca-cache' ],
  47. [ 'dram-cache', .01, 'DataCachedram-cache' ],
  48. [ 'dram', .01, ('DataCachedram', 'DataCachedram-local', 'DataCachedram-remote',
  49. 'DataCachemiss', 'DataCache????', 'DataCachepredicate-false', 'DataCacheprefetch-no-mapping', 'DataCacheunknown') ],
  50. ] ],
  51. ]
  52. else:
  53. items += [
  54. [ 'mem', .01, [
  55. [ 'l0d_neighbor', .01, 'DataCacheL1_S' ],
  56. [ 'l1d', .01, ('DataCacheL1', 'PathLoadX', 'PathStore') ],
  57. [ 'l1_neighbor', .01, 'DataCacheL2_S' ],
  58. [ 'l2', .01, 'DataCacheL2' ],
  59. [ 'l2_neighbor', .01, 'DataCacheL3_S' ],
  60. [ 'l3', .01, 'DataCacheL3' ],
  61. [ 'l3_neighbor', .01, 'DataCacheL4_S' ],
  62. [ 'l4', .01, 'DataCacheL4' ],
  63. [ 'off_socket', .01, 'DataCachecache-remote' ],
  64. [ 'nuca', .01, 'DataCachenuca-cache' ],
  65. [ 'dram-cache', .01, 'DataCachedram-cache' ],
  66. [ 'dram', .01, ('DataCachedram', 'DataCachedram-local', 'DataCachedram-remote',
  67. 'DataCachemiss', 'DataCache????', 'DataCachepredicate-false', 'DataCacheunknown') ],
  68. ] ],
  69. ]
  70. if use_simple_sync:
  71. items += [ [ 'sync', .01, ('SyncFutex', 'SyncPthreadMutex', 'SyncPthreadCond', 'SyncPthreadBarrier', 'SyncJoin',
  72. 'SyncPause', 'SyncSleep', 'SyncUnscheduled', 'SyncMemAccess', 'Recv' ) ] ]
  73. else:
  74. items += [
  75. [ 'sync', .01, [
  76. [ 'futex', .01, 'SyncFutex' ],
  77. [ 'mutex', .01, 'SyncPthreadMutex' ],
  78. [ 'cond', .01, 'SyncPthreadCond' ],
  79. [ 'barrier', .01, 'SyncPthreadBarrier' ],
  80. [ 'join', .01, 'SyncJoin' ],
  81. [ 'pause', .01, 'SyncPause' ],
  82. [ 'sleep', .01, 'SyncSleep' ],
  83. [ 'syscall', .01, 'SyncSyscall' ],
  84. [ 'unscheduled', .01, 'SyncUnscheduled' ],
  85. [ 'memaccess',.01, 'SyncMemAccess' ],
  86. [ 'recv', .01, 'Recv' ],
  87. ] ],
  88. ]
  89. items += [
  90. [ 'dvfs-transition', 0.01, 'SyncDvfsTransition' ],
  91. [ 'imbalance', 0.01, [
  92. [ 'start', 0.01, ('StartTime', 'Unknown') ],
  93. [ 'end', 0.01, 'Imbalance' ],
  94. ] ],
  95. ]
  96. return items
  97. def build_grouplist(legacy = False):
  98. # List of <groupname>, <base color>, <list of items>
  99. # Used to collaps items when use_simple is true, and for coloring
  100. if legacy:
  101. return [
  102. ('compute', (0xff,0,0), ('dispatch_width', 'rs_full', 'base', 'issue', 'depend',
  103. 'branch', 'serial', 'smt')),
  104. ('communicate', (0,0xff,0), ('itlb','dtlb','ifetch','mem',)),
  105. ('synchronize', (0,0,0xff), ('sync', 'recv', 'dvfs-transition', 'imbalance')),
  106. ]
  107. else:
  108. return [
  109. ('compute', (0xff,0,0), ('dispatch_width', 'rs_full', 'base', 'issue', 'depend', 'serial', 'smt')),
  110. ('branch', (0xff,0xff,0), ('branch',)),
  111. ('memory', (0,0xff,0), ('itlb','dtlb','ifetch','mem',)),
  112. ('synchronize', (0,0,0xff), ('sync', 'recv', 'dvfs-transition', 'imbalance')),
  113. ]
  114. class CpiItems:
  115. def __init__(self, items = None, groups = None, use_simple = False, use_simple_sync = False, use_simple_mem = True):
  116. self.items = items or build_itemlist(use_simple_sync, use_simple_mem)
  117. self.groups = groups or build_grouplist()
  118. if use_simple:
  119. self.compact_by_group()
  120. self.gen_contributions()
  121. self.names = buildstack.get_names(self.items)
  122. self.add_other()
  123. def compact_by_group(self):
  124. def _findall(items, keys = None):
  125. res = []
  126. for name, threshold, key_or_items in items:
  127. if not keys or name in keys:
  128. if type(key_or_items) is list:
  129. res += _findall(key_or_items)
  130. elif type(key_or_items) is tuple:
  131. res += list(key_or_items)
  132. else:
  133. res += [ key_or_items ]
  134. return res
  135. def findall(*keys): return tuple(_findall(self.items, keys))
  136. new_all_items = []
  137. new_simple_groups = []
  138. for name, color, items in self.groups:
  139. new_all_items.append([name, 0, findall(*items)])
  140. new_simple_groups.append((name, color, (name,)))
  141. self.items = new_all_items
  142. self.groups = new_simple_groups
  143. def gen_contributions(self):
  144. self.names_to_contributions = {}
  145. for group, color, members in self.groups:
  146. for name in buildstack.get_names(self.items, keys = members):
  147. self.names_to_contributions[name] = group
  148. def add_other(self):
  149. self.groups.append(('other', (0,0,0), ('other',)))
  150. self.names.append('other')
  151. self.names_to_contributions['other'] = 'other'
  152. def get_colors(self, labels_used = None):
  153. if labels_used:
  154. # Make sure labels is a sorted list of valid labels
  155. labels = [ label for label in self.names if label in labels_used ]
  156. else:
  157. labels = self.names
  158. return get_colors(labels, self.groups, self.names_to_contributions)
  159. # Color helper functions
  160. def color_tint_shade(base_color, num):
  161. base_color = map(lambda x:float(x)/255, base_color)
  162. base_color = colorsys.rgb_to_hsv(*base_color)
  163. colors = []
  164. delta = 0.6 / float((num/2) or 1)
  165. shade = 1.0
  166. for _ in range(num/2):
  167. shade -= delta
  168. colors.append((base_color[0],base_color[1],shade))
  169. colors = colors[::-1] # Reverse
  170. if num % 2 == 1:
  171. colors.append(base_color)
  172. tint = 1.0
  173. for _ in range(num/2):
  174. tint -= delta
  175. colors.append((base_color[0],tint,base_color[2]))
  176. colors = map(lambda x:colorsys.hsv_to_rgb(*x),colors)
  177. colors = map(lambda x:tuple(map(lambda y:int(y*255),x)),colors)
  178. return colors
  179. def get_colors(labels, groups, names_to_contributions):
  180. contribution_counts = collections.defaultdict(int)
  181. for i in labels:
  182. contribution_counts[names_to_contributions[i]] += 1
  183. color_ranges = {}
  184. next_color_index = {}
  185. for name, color, _ in groups:
  186. color_ranges[name] = color_tint_shade(color, contribution_counts[name])
  187. next_color_index[name] = 0
  188. def get_next_color(contr):
  189. idx = next_color_index[contr]
  190. next_color_index[contr] += 1
  191. return color_ranges[contr][idx]
  192. return dict([ (label, get_next_color(names_to_contributions[label])) for label in labels ])