1 from __future__
import print_function
10 from Configurables
import GaudiSequencer, CPUCruncher
15 if not os.path.exists(filePath):
16 __fullFilePath__ = os.path.realpath(
18 os.environ.get(
'GAUDIHIVEROOT',
''),
"data", filePath))
19 if not os.path.exists(__fullFilePath__):
21 "\nERROR: invalid file path '%s'. It must be either absolute, or relative to '$GAUDIHIVEROOT/data/'." 25 __fullFilePath__ = filePath
27 return __fullFilePath__
31 """A class to manage uniform algorithm timing""" 38 def get(self, algoName=''):
39 """Get time and its variance (in a tuple) for a given algorithm name""" 45 """A class to manage real algorithm timing""" 47 def __init__(self, path, defaultTime, factor=1):
49 defaultTime -- run time, assigned to an algorithm if no time is found in provided timing library 50 (and it will also be scaled by the 'factor' argument) 61 def get(self, algoName=''):
62 """Get time for a given algorithm name""" 65 time = float(self.
timings[algoName])
67 capAlgoName = algoName[0].upper() + algoName[1:len(algoName)]
70 time = float(self.
timings[capAlgoName])
74 "WARNING: TimiNg for %s (or %s) not found in the provided library, using default one: %s" 75 % (algoName, capAlgoName, time))
93 """Provides randomly ordered set of boolean values with requested proportion of True and False.""" 98 pattern -- either a dictionary describing proportion of True and False (e.g., {True:5,False:15}), or 99 a list/tuple containing a pattern to be used as-is (e.g., [False,True,True,False]) 100 seed -- an int, long or other hashable object to initialize random number generator (passed to random.shuffle as-is) 103 if isinstance(pattern, dict):
106 length = proportion[
True] + proportion[
False]
108 raise "ERROR: Wrong set length requested: %i " % length
111 ] + [
True for i
in range(proportion[
True])]
118 elif isinstance(pattern, (list, tuple)):
121 raise "ERROR: unknown pattern type" 140 """Constructs the sequence tree of CPUCrunchers with provided control flow and data flow precedence rules.""" 142 unique_sequencers = []
148 unique_data_objects = []
162 timeValue -- timeValue object to set algorithm execution time 163 IOboolValue -- *BooleanValue object to set whether an algorithm has to experience IO-bound execution 164 cfgPath -- relative to $GAUDIHIVEROOT/data path to GRAPHML file with control flow dependencies 165 dfgPath -- relative to $GAUDIHIVEROOT/data path to GRAPHML file with data flow dependencies 166 showStat -- print out statistics on precedence graph 186 print(
"\n===== Statistics on Algorithms =====")
187 print(
"Total number of algorithm nodes: ", len(self.
unique_algos) +
189 print(
"Number of unique algorithms: ", len(self.
unique_algos))
191 "of them being re-used with the following distribution: ",
195 print(
"\n===== Statistics on Sequencers =====")
200 "of them being re-used with the following distribution: ",
205 print(
"\n===== Statistics on DataObjects =====")
206 print(
"Number of unique DataObjects: ",
216 """ Declare data inputs and outputs for a given algorithm. """ 219 for inNode, outNode
in self.
dfg.in_edges(algo_name):
224 if dataName
not in algo.inpKeys:
225 algo.inpKeys.append(dataName)
228 for inNode, outNode
in self.
dfg.out_edges(algo_name):
233 if dataName
not in algo.outKeys:
234 algo.outKeys.append(dataName)
237 """ Assemble the tree of sequencers. """ 240 seq = GaudiSequencer(name, ShortCircuit=
False)
242 for n
in self.
cfg[name]:
244 algo_name = n.split(
'/')[1]
if '/' in n
else n
246 if 'type' in self.
cfg.node[n]:
248 algo_type = self.
cfg.node[n].
get(
'type')
252 algo_type = n.split(
'/')[0]
if '/' in n
else 'Algorithm' 254 if algo_type
in [
'GaudiSequencer',
'AthSequencer',
'ProcessPhase']:
255 if algo_name
in [
'RecoITSeq',
'RecoOTSeq',
'RecoTTSeq']:
266 seq_daughter = GaudiSequencer(algo_name, OutputLevel=INFO)
267 if self.
cfg.node[n].
get(
'ModeOR') ==
'True':
269 seq_daughter.ModeOR =
True 272 seq_daughter.ShortCircuit =
False 273 if seq_daughter
not in seq.Members:
274 seq.Members += [seq_daughter]
290 algo_daughter = CPUCruncher(
293 varRuntime=varRuntime,
294 avgRuntime=avgRuntime,
301 if algo_daughter
not in seq.Members:
302 seq.Members += [algo_daughter]
def __init__(self, path, defaultTime, factor=1)
def _generate_sequence(self, name, seq=None)
def get(self, algoName='')
def __init__(self, timeValue, IOboolValue, sleepFraction, cfgPath, dfgPath, topSequencer, showStat=False, timeline=False, outputLevel=INFO)
def _declare_data_deps(self, algo_name, algo)
def _buildFilePath(filePath)
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
def __init__(self, pattern, seed=None)
def _create_generator(self, pattern)