123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- #!/usr/bin/python
- ##
- # StarPU --- Runtime system for heterogeneous multicore architectures.
- #
- # Copyright (C) 2016 INRIA
- #
- # StarPU is free software; you can redistribute it and/or modify
- # it under the terms of the GNU Lesser General Public License as published by
- # the Free Software Foundation; either version 2.1 of the License, or (at
- # your option) any later version.
- #
- # StarPU is distributed in the hope that it will be useful, but
- # WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- #
- # See the GNU Lesser General Public License in COPYING.LGPL for more details.
- ##
- ##
- # This script parses the generated trace.rec file and reports statistics about
- # the number of different events/tasks and their durations. The report is
- # similar to the starpu_paje_state_stats.in script, except that this one
- # doesn't need R and pj_dump (from the pajeng repository), and it is also much
- # faster.
- ##
- import getopt
- import os
- import sys
- class Event():
- def __init__(self, type, name, start_time):
- self._type = type
- self._name = name
- self._start_time = start_time
- class EventStats():
- def __init__(self, name, duration_time, count = 1):
- self._name = name
- self._duration_time = duration_time
- self._count = count
- def aggregate(self, duration_time):
- self._duration_time += duration_time
- self._count += 1
- def show(self):
- if not self._name == None:
- print "\"" + self._name + "\"," + str(self._count) + "," + str(round(self._duration_time, 6))
- class Worker():
- def __init__(self, id):
- self._id = id
- self._events = []
- self._stats = []
- self._stack = []
- def get_event_stats(self, name):
- for stat in self._stats:
- if stat._name == name:
- return stat
- return None
- def add_event(self, type, name, start_time):
- self._events.append(Event(type, name, start_time))
- def calc_stats(self):
- num_events = len(self._events) - 1
- for i in xrange(0, num_events):
- curr_event = self._events[i]
- next_event = self._events[i+1]
- if next_event._type == "PushState":
- self._stack.append(next_event)
- for j in xrange(i+1, num_events):
- next_event = self._events[j]
- if next_event._type == "SetState":
- break
- elif next_event._type == "PopState":
- curr_event = self._stack.pop()
- # Compute duration with the next event.
- a = curr_event._start_time
- b = next_event._start_time
- found = False
- for j in xrange(len(self._stats)):
- if self._stats[j]._name == curr_event._name:
- self._stats[j].aggregate(b - a)
- found = True
- break
- if not found == True:
- self._stats.append(EventStats(curr_event._name, b - a))
- def read_blocks(input_file):
- empty_lines = 0
- first_line = 1
- blocks = []
- for line in open(input_file):
- if first_line:
- blocks.append([])
- blocks[-1].append(line)
- first_line = 0
- # Check for empty lines
- if not line or line[0] == '\n':
- # If 1st one: new block
- if empty_lines == 0:
- blocks.append([])
- empty_lines += 1
- else:
- # Non empty line: add line in current(last) block
- empty_lines = 0
- blocks[-1].append(line)
- return blocks
- def read_field(field, index):
- return field[index+1:-1]
- def insert_worker_event(workers, block):
- worker_id = -1
- name = None
- start_time = 0.0
- for line in block:
- if line[:2] == "E:": # EventType
- event_type = read_field(line, 2)
- elif line[:2] == "W:": # WorkerId
- worker_id = int(read_field(line, 2))
- elif line[:2] == "N:": # Name
- name = read_field(line, 2)
- elif line[:2] == "S:": # StartTime
- start_time = float(read_field(line, 2))
- for worker in workers:
- if worker._id == worker_id:
- worker.add_event(event_type, name, start_time)
- return
- worker = Worker(worker_id)
- worker.add_event(event_type, name, start_time)
- workers.append(worker)
- def main():
- if len(sys.argv) != 2:
- print sys.argv[0] + " <trace.rec>"
- sys.exit(1)
- recfile = sys.argv[1]
- if not os.path.isfile(recfile):
- sys.exit("File does not exist!")
- # Declare a list for all workers.
- workers = []
- # Read the recutils file format per blocks.
- blocks = read_blocks(recfile)
- for block in blocks:
- if not len(block) == 0:
- first_line = block[0]
- if first_line[:2] == "E:":
- insert_worker_event(workers, block)
- # Compute worker statistics.
- stats = []
- for worker in workers:
- worker.calc_stats()
- for stat in worker._stats:
- found = False
- for s in stats:
- if stat._name == s._name:
- found = True
- break
- if not found == True:
- stats.append(EventStats(stat._name, 0.0, 0))
- # Compute global statistics for all workers.
- for i in xrange(0, len(workers)):
- for stat in stats:
- s = workers[i].get_event_stats(stat._name)
- if not s == None:
- # A task might not be executed on all workers.
- stat._duration_time += s._duration_time
- stat._count += s._count
- # Output statistics.
- print "\"Value\",\"Events\",\"Duration\""
- for stat in stats:
- stat.show()
- if __name__ == "__main__":
- main()
|