9 from Configurables
import GaudiSequencer, CPUCruncher
14 if not os.path.exists(filePath):
15 __fullFilePath__ = os.path.realpath(
17 os.environ.get(
'GAUDIHIVEROOT',
''),
"data", filePath))
18 if not os.path.exists(__fullFilePath__):
19 print "\nERROR: invalid file path '%s'. It must be either absolute, or relative to '$GAUDIHIVEROOT/data/'." % filePath
22 __fullFilePath__ = filePath
24 return __fullFilePath__
28 """A class to manage uniform algorithm timing""" 35 def get(self, algoName=''):
36 """Get time and its variance (in a tuple) for a given algorithm name""" 42 """A class to manage real algorithm timing""" 44 def __init__(self, path, defaultTime, factor=1):
46 defaultTime -- run time, assigned to an algorithm if no time is found in provided timing library 47 (and it will also be scaled by the 'factor' argument) 58 def get(self, algoName=''):
59 """Get time for a given algorithm name""" 62 time = float(self.
timings[algoName])
64 capAlgoName = algoName[0].upper() + algoName[1:len(algoName)]
67 time = float(self.
timings[capAlgoName])
70 print "WARNING: TimiNg for %s (or %s) not found in the provided library, using default one: %s" % (
71 algoName, capAlgoName, time)
89 """Provides randomly ordered set of boolean values with requested proportion of True and False.""" 94 pattern -- either a dictionary describing proportion of True and False (e.g., {True:5,False:15}), or 95 a list/tuple containing a pattern to be used as-is (e.g., [False,True,True,False]) 96 seed -- an int, long or other hashable object to initialize random number generator (passed to random.shuffle as-is) 99 if isinstance(pattern, dict):
102 length = proportion[
True] + proportion[
False]
104 raise "ERROR: Wrong set length requested: %i " % length
107 ] + [
True for i
in range(proportion[
True])]
114 elif isinstance(pattern, (list, tuple)):
117 raise "ERROR: unknown pattern type" 136 """Constructs the sequence tree of CPUCrunchers with provided control flow and data flow precedence rules.""" 138 unique_sequencers = []
144 unique_data_objects = []
158 timeValue -- timeValue object to set algorithm execution time 159 IOboolValue -- *BooleanValue object to set whether an algorithm has to experience IO-bound execution 160 cfgPath -- relative to $GAUDIHIVEROOT/data path to GRAPHML file with control flow dependencies 161 dfgPath -- relative to $GAUDIHIVEROOT/data path to GRAPHML file with data flow dependencies 162 showStat -- print out statistics on precedence graph 182 print "\n===== Statistics on Algorithms =====" 183 print "Total number of algorithm nodes: ", len(
186 print "Number of unique algorithms: ", len(self.
unique_algos)
189 ),
"of them being re-used with the following distribution: ", [
194 print "\n===== Statistics on Sequencers =====" 195 print "Total number of sequencers: ", len(
201 ),
"of them being re-used with the following distribution: ", [
207 print "\n===== Statistics on DataObjects =====" 208 print "Number of unique DataObjects: ", len(
218 """ Declare data inputs and outputs for a given algorithm. """ 221 for inNode, outNode
in self.dfg.in_edges(algo_name):
224 self.unique_data_objects.append(dataName)
226 if dataName
not in algo.inpKeys:
227 algo.inpKeys.append(dataName)
230 for inNode, outNode
in self.dfg.out_edges(algo_name):
233 self.unique_data_objects.append(dataName)
235 if dataName
not in algo.outKeys:
236 algo.outKeys.append(dataName)
239 """ Assemble the tree of sequencers. """ 242 seq = GaudiSequencer(name, ShortCircuit=
False)
244 for n
in self.
cfg[name]:
246 algo_type, algo_name = n.split(
'/')
248 algo_type =
'GaudiAlgorithm' 251 if algo_type
in [
'GaudiSequencer',
'AthSequencer',
'ProcessPhase']:
252 if algo_name
in [
'RecoITSeq',
'RecoOTSeq',
'RecoTTSeq']:
256 self.unique_sequencers.append(n)
263 seq_daughter = GaudiSequencer(algo_name, OutputLevel=INFO)
264 if self.cfg.node[n].
get(
'ModeOR') ==
'True':
265 self.OR_sequencers.append(n)
266 seq_daughter.ModeOR =
True 269 seq_daughter.ShortCircuit =
False 270 if seq_daughter
not in seq.Members:
271 seq.Members += [seq_daughter]
278 self.unique_algos.append(n)
285 avgRuntime, varRuntime = self.timeValue.get(algo_name)
286 algo_daughter = CPUCruncher(
289 varRuntime=varRuntime,
290 avgRuntime=avgRuntime,
292 if self.IOboolValue.get()
else 0.,
297 if algo_daughter
not in seq.Members:
298 seq.Members += [algo_daughter]
def __init__(self, path, defaultTime, factor=1)
def _generate_sequence(self, name, seq=None)
double sum(double x, double y, double z)
def get(self, algoName='')
def __init__(self, timeValue, IOboolValue, sleepFraction, cfgPath, dfgPath, topSequencer, showStat=False, timeline=False, outputLevel=INFO)
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
def _declare_data_deps(self, algo_name, algo)
def _buildFilePath(filePath)
def __init__(self, pattern, seed=None)
def _create_generator(self, pattern)