Peano
Loading...
Searching...
No Matches
OutputFile.py
Go to the documentation of this file.
1# This file is part of Peano's loadbalancing toolbox. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3
4class OutputFile(object):
5 """!
6
7 Represents single output file dumped by Peano
8
9 This class extracts all the load balancing-related information from
10 an output file, i.e. is basically an abstraction of a file parser.
11 It also holds some very basic runtime data.
12
13 @param name File name
14 """
15 def __init__(self,
16 name,
17 verbose = False
18 ):
19
20 self._file_name = name
21 self._has_parsed = False
22 self._verbose = verbose
23 pass
24
25
26 def parse(self):
27 """!
28
29 Parse Peano output file
30
31 Build up a tuple of (x_data,y_data_local,y_data_remote) internally
32 but also extract some meta data
33
34 """
35
36 if self._has_parsed:
37 return
38 self._has_parsed = True
39
40 if self._verbose:
41 print( "parse file {}".format( self._file_name) )
42
43 file = open( self._file_name, "r" )
44
46
47 for line in file:
48 if "build:" in line and "no mpi" in line:
49 if self._verbose:
50 print( "code does not use MPI" )
51 self._ranks = 1
52 if "build:" in line and "threads" in line:
53 self._threads = int( line.split( "threads" )[0].split( "(" )[-1])
54 if self._verbose:
55 print( "code uses " + str(self._threads) + " threads per rank" )
56 if "manually reset number of threads used to" in line:
57 self._threads = int( line.split( "to" )[1])
58 if self._verbose:
59 print( "code sets number of threads manually to " + str(self._threads) )
60 if "build:" in line and "ranks)" in line:
61 self._ranks = int( line.split( "ranks)" )[0].split("(")[1])
62 if self._verbose:
63 print( "code uses " + str(self._ranks) + " ranks" )
64
65 if "time stepping:" in line:
66 self._runtime = float( line.split( "time stepping:" )[1].split( "s")[0] )
67 if self._verbose:
68 print( "code runs for " + str(self._runtime) + "s" )
69
70
71 if "toolbox::loadbalancing::dumpStatistics" in line:
72 if "rank:" in line:
73 current_rank = int( line.split( "rank:" )[1].split(" ")[0] )
74 else:
75 current_rank = 0
76 if not current_rank in self._snapshot_lines:
77 self._snapshot_lines[ current_rank ] = []
78 if self._verbose:
79 print( "create new dataset for rank {}".format(current_rank) )
80
81 self._snapshot_lines[ current_rank ].append( line.split( "toolbox::loadbalancing::dumpStatistics()")[1] )
82
83 assert current_rank in self._snapshot_lines
84
85
86
87
88 @property
89 def ranks(self):
90 self.parse()
91 return self._ranks
92
93
94 @property
96 self.parse()
97 return self._threads
98
99
100 @property
101 def runtime(self):
102 """!
103
104 Read out the total runtime
105
106 """
107 self.parse()
108 return self._runtime
109
110
112 rank
113 ):
114 """!
115
116 Return a sequence of integers that holds the number of trees per snapshot
117
118 """
119 self.parse()
120 assert rank>=0
121 assert rank<self._ranks
122
123 result = []
124 for entry in self._snapshot_lines[rank]:
125 number_of_trees = int( entry.split( "tree(s)" )[0] )
126 result.append( number_of_trees )
127
128 return result
129
130
132 rank
133 ):
134 """!
135
136 Return local cells per snaphot
137
138 This is a sequence of sequences. For each snapshot for this
139 rank, we store one sequence with all the local cells in this
140 snapshot. The standard plot_load_distribution.py script feeds
141 this data into a scatter plot. For many cases, we might however
142 be interested in the maximum value:
143
144 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
145 raw_data = ouput_file.local_cells_per_snapshot(rank)
146 max_data = [max(x) for x in raw_data ]
147 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
148
149 """
150 self.parse()
151 assert rank>=0
152 assert rank<self._ranks
153
154 result = []
155 for snapshot in self._snapshot_lines[rank]:
156 result.append( [] )
157 tree_entries_in_line = snapshot.split( "(#")
158 for tree_entry in tree_entries_in_line[1:]:
159 new_count = int( tree_entry.split(":")[1].split("/")[0] )
160 result[-1].append(new_count)
161
162 return result
163
164
166 rank
167 ):
168 """!
169
170 Return local cells per snaphot
171
172 This is a sequence of sequences. For each snapshot for this
173 rank, we store one sequence with all the local cells in this
174 snapshot.
175
176 """
177 self.parse()
178 assert rank>=0
179 assert rank<self._ranks
180
181 result = []
182 for snapshot in self._snapshot_lines[rank]:
183 result.append( [] )
184 tree_entries_in_line = snapshot.split( "(#")
185 for tree_entry in tree_entries_in_line[1:]:
186 new_count = int( tree_entry.split("/")[1].split(")")[0] )
187 result[-1].append(new_count)
188
189 return result
190
191
193 rank
194 ):
195 """!
196
197 Return the total number of cells per snapshot for this rank
198
199 The total number of cells is an interesting quantity, as it allows
200 us to compare the load of different ranks.
201
202 """
203 local_cell_per_snapshot = self.local_cells_per_snapshot( rank )
204
205 result = []
206 for snapshot_data in local_cell_per_snapshot:
207 new_entry = sum( snapshot_data )
208 result.append(new_entry)
209 return result
210
211
213 rank
214 ):
215 """!
216
217 Return the total number of cells per snapshot for this rank
218
219 The total number of cells is an interesting quantity, as it allows
220 us to compare the load of different ranks.
221
222 """
223 local_cell_per_snapshot = self.local_cells_per_snapshot( rank )
224
225 result = []
226 for snapshot_data in local_cell_per_snapshot:
227 new_entry = min( snapshot_data )
228 result.append(new_entry)
229 return result
230
231
233 rank
234 ):
235 """!
236
237 Return the total number of cells per snapshot for this rank
238
239 The total number of cells is an interesting quantity, as it allows
240 us to compare the load of different ranks.
241
242 """
243 local_cell_per_snapshot = self.local_cells_per_snapshot( rank )
244
245 result = []
246 for snapshot_data in local_cell_per_snapshot:
247 new_entry = max( snapshot_data )
248 result.append(new_entry)
249 return result
250
251
253 rank
254 ):
255 """!
256
257 Return the total number of cells per snapshot for this rank
258
259 The total number of cells is an interesting quantity, as it allows
260 us to compare the load of different ranks.
261
262 """
263 virtual_cell_per_snapshot = self.virtual_cells_per_snapshot( rank )
264
265 result = []
266 for snapshot_data in virtual_cell_per_snapshot:
267 new_entry = min( snapshot_data )
268 result.append(new_entry)
269 return result
270
271
273 rank
274 ):
275 """!
276
277 Return the total number of cells per snapshot for this rank
278
279 The total number of cells is an interesting quantity, as it allows
280 us to compare the load of different ranks.
281
282 """
283 virtual_cell_per_snapshot = self.virtual_cells_per_snapshot( rank )
284
285 result = []
286 for snapshot_data in virtual_cell_per_snapshot:
287 new_entry = max( snapshot_data )
288 result.append(new_entry)
289 return result
290
291
292 def is_valid(self):
293 return hasattr(self, "_runtime")
294
Represents single output file dumped by Peano.
Definition OutputFile.py:4
min_local_cells_per_snapshot(self, rank)
Return the total number of cells per snapshot for this rank.
total_local_cells_per_snapshot(self, rank)
Return the total number of cells per snapshot for this rank.
min_virtual_cells_per_snapshot(self, rank)
Return the total number of cells per snapshot for this rank.
trees_per_snapshot(self, rank)
Return a sequence of integers that holds the number of trees per snapshot.
virtual_cells_per_snapshot(self, rank)
Return local cells per snaphot.
__init__(self, name, verbose=False)
Definition OutputFile.py:18
runtime(self)
Read out the total runtime.
max_local_cells_per_snapshot(self, rank)
Return the total number of cells per snapshot for this rank.
parse(self)
Parse Peano output file.
Definition OutputFile.py:26
local_cells_per_snapshot(self, rank)
Return local cells per snaphot.
max_virtual_cells_per_snapshot(self, rank)
Return the total number of cells per snapshot for this rank.