starpu_trace_state_stats.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #!/usr/bin/python
  2. ##
  3. # StarPU --- Runtime system for heterogeneous multicore architectures.
  4. #
  5. # Copyright (C) 2016 INRIA
  6. #
  7. # StarPU is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU Lesser General Public License as published by
  9. # the Free Software Foundation; either version 2.1 of the License, or (at
  10. # your option) any later version.
  11. #
  12. # StarPU is distributed in the hope that it will be useful, but
  13. # WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. #
  16. # See the GNU Lesser General Public License in COPYING.LGPL for more details.
  17. ##
  18. ##
  19. # This script parses the generated trace.rec file and reports statistics about
  20. # the number of different events/tasks and their durations. The report is
  21. # similar to the starpu_paje_state_stats.in script, except that this one
  22. # doesn't need R and pj_dump (from the pajeng repository), and it is also much
  23. # faster.
  24. ##
  25. import getopt
  26. import os
  27. import sys
  28. class Event():
  29. def __init__(self, type, name, start_time):
  30. self._type = type
  31. self._name = name
  32. self._start_time = start_time
  33. class EventStats():
  34. def __init__(self, name, duration_time, count = 1):
  35. self._name = name
  36. self._duration_time = duration_time
  37. self._count = count
  38. def aggregate(self, duration_time):
  39. self._duration_time += duration_time
  40. self._count += 1
  41. def show(self):
  42. if not self._name == None:
  43. print "\"" + self._name + "\"," + str(self._count) + "," + str(round(self._duration_time, 6))
  44. class Worker():
  45. def __init__(self, id):
  46. self._id = id
  47. self._events = []
  48. self._stats = []
  49. self._stack = []
  50. def get_event_stats(self, name):
  51. for stat in self._stats:
  52. if stat._name == name:
  53. return stat
  54. return None
  55. def add_event(self, type, name, start_time):
  56. self._events.append(Event(type, name, start_time))
  57. def calc_stats(self):
  58. num_events = len(self._events) - 1
  59. for i in xrange(0, num_events):
  60. curr_event = self._events[i]
  61. next_event = self._events[i+1]
  62. if next_event._type == "PushState":
  63. self._stack.append(next_event)
  64. for j in xrange(i+1, num_events):
  65. next_event = self._events[j]
  66. if next_event._type == "SetState":
  67. break
  68. elif next_event._type == "PopState":
  69. curr_event = self._stack.pop()
  70. # Compute duration with the next event.
  71. a = curr_event._start_time
  72. b = next_event._start_time
  73. found = False
  74. for j in xrange(len(self._stats)):
  75. if self._stats[j]._name == curr_event._name:
  76. self._stats[j].aggregate(b - a)
  77. found = True
  78. break
  79. if not found == True:
  80. self._stats.append(EventStats(curr_event._name, b - a))
  81. def read_blocks(input_file):
  82. empty_lines = 0
  83. first_line = 1
  84. blocks = []
  85. for line in open(input_file):
  86. if first_line:
  87. blocks.append([])
  88. blocks[-1].append(line)
  89. first_line = 0
  90. # Check for empty lines
  91. if not line or line[0] == '\n':
  92. # If 1st one: new block
  93. if empty_lines == 0:
  94. blocks.append([])
  95. empty_lines += 1
  96. else:
  97. # Non empty line: add line in current(last) block
  98. empty_lines = 0
  99. blocks[-1].append(line)
  100. return blocks
  101. def read_field(field, index):
  102. return field[index+1:-1]
  103. def insert_worker_event(workers, block):
  104. worker_id = -1
  105. name = None
  106. start_time = 0.0
  107. for line in block:
  108. if line[:2] == "E:": # EventType
  109. event_type = read_field(line, 2)
  110. elif line[:2] == "W:": # WorkerId
  111. worker_id = int(read_field(line, 2))
  112. elif line[:2] == "N:": # Name
  113. name = read_field(line, 2)
  114. elif line[:2] == "S:": # StartTime
  115. start_time = float(read_field(line, 2))
  116. for worker in workers:
  117. if worker._id == worker_id:
  118. worker.add_event(event_type, name, start_time)
  119. return
  120. worker = Worker(worker_id)
  121. worker.add_event(event_type, name, start_time)
  122. workers.append(worker)
  123. def main():
  124. if len(sys.argv) != 2:
  125. print sys.argv[0] + " <trace.rec>"
  126. sys.exit(1)
  127. recfile = sys.argv[1]
  128. if not os.path.isfile(recfile):
  129. sys.exit("File does not exist!")
  130. # Declare a list for all workers.
  131. workers = []
  132. # Read the recutils file format per blocks.
  133. blocks = read_blocks(recfile)
  134. for block in blocks:
  135. if not len(block) == 0:
  136. first_line = block[0]
  137. if first_line[:2] == "E:":
  138. insert_worker_event(workers, block)
  139. # Compute worker statistics.
  140. stats = []
  141. for worker in workers:
  142. worker.calc_stats()
  143. for stat in worker._stats:
  144. found = False
  145. for s in stats:
  146. if stat._name == s._name:
  147. found = True
  148. break
  149. if not found == True:
  150. stats.append(EventStats(stat._name, 0.0, 0))
  151. # Compute global statistics for all workers.
  152. for i in xrange(0, len(workers)):
  153. for stat in stats:
  154. s = workers[i].get_event_stats(stat._name)
  155. if not s == None:
  156. # A task might not be executed on all workers.
  157. stat._duration_time += s._duration_time
  158. stat._count += s._count
  159. # Output statistics.
  160. print "\"Value\",\"Events\",\"Duration\""
  161. for stat in stats:
  162. stat.show()
  163. if __name__ == "__main__":
  164. main()