11 from __future__
import print_function
22 warnings.filterwarnings(
"ignore", message=
'"is" with a literal', category=SyntaxWarning)
25 from Configurables
import CPUCruncher, GaudiSequencer
31 if not os.path.exists(filePath):
32 __fullFilePath__ = os.path.realpath(
34 os.environ.get(
"ENV_PROJECT_SOURCE_DIR",
""),
40 if not os.path.exists(__fullFilePath__):
41 __fullFilePath__ = os.path.realpath(
43 os.environ.get(
"ENV_PROJECT_SOURCE_DIR",
""),
50 if not os.path.exists(__fullFilePath__):
52 "\nERROR: invalid file path '%s'. "
53 "It must be either absolute, or relative to "
54 "'$ENV_PROJECT_SOURCE_DIR/GaudiHive/data/' or to "
55 "'$ENV_PROJECT_SOURCE_DIR/Gaudi/GaudiHive/data/'." % filePath
59 __fullFilePath__ = filePath
61 return __fullFilePath__
65 """A class to manage uniform algorithm timing"""
72 def get(self, algoName=""):
73 """Get time and its variance (in a tuple) for a given algorithm name"""
79 """A class to manage real algorithm timing"""
81 def __init__(self, path, defaultTime, factor=1):
83 defaultTime -- run time, assigned to an algorithm if no time is found in provided timing library
84 (and it will also be scaled by the 'factor' argument)
95 def get(self, algoName=""):
96 """Get time for a given algorithm name"""
99 time = float(self.
timings[algoName])
101 capAlgoName = algoName[0].upper() + algoName[1 : len(algoName)]
103 if capAlgoName
in self.
timings:
104 time = float(self.
timings[capAlgoName])
108 "WARNING: Timing for %s (or %s) not found in the provided library, using default one: %s"
109 % (algoName, capAlgoName, time)
128 """Provides randomly ordered set of boolean values with requested proportion of True and False."""
133 pattern -- either a dictionary describing proportion of True and False (e.g., {True:5,False:15}), or
134 a list/tuple containing a pattern to be used as-is (e.g., [False,True,True,False])
135 seed -- an int, long or other hashable object to initialize random number generator (passed to random.shuffle as-is)
138 if isinstance(pattern, dict):
141 length = proportion[
True] + proportion[
False]
143 raise "ERROR: Wrong set length requested: %i " % length
146 True for i
in range(proportion[
True])
154 elif isinstance(pattern, (list, tuple)):
157 raise "ERROR: unknown pattern type"
176 """Constructs the sequence tree of CPUCrunchers with provided control flow and data flow precedence rules."""
178 unique_sequencers = []
184 unique_data_objects = []
201 timeValue -- timeValue object to set algorithm execution time
202 BlockingBoolValue -- *BooleanValue object to set whether an algorithm has to experience CPU-blocking execution
203 cfgPath -- relative to $ENV_PROJECT_SOURCE_DIR/GaudiHive/data path to GRAPHML file with control flow dependencies
204 dfgPath -- relative to $ENV_PROJECT_SOURCE_DIR/GaudiHive/data path to GRAPHML file with data flow dependencies
205 showStat -- print out statistics on precedence graph
226 print(
"\n===== Statistics on Algorithms =====")
228 "Total number of algorithm nodes: ",
232 print(
"Number of unique algorithms: ", len(self.
unique_algos))
236 "of them being re-used with the following distribution: ",
241 print(
"\n===== Statistics on Sequencers =====")
243 "Total number of sequencers: ",
251 "of them being re-used with the following distribution: ",
257 print(
"\n===== Statistics on DataObjects =====")
267 """Declare data inputs and outputs for a given algorithm."""
270 for inNode, outNode
in self.
dfg.in_edges(algo_name):
275 if dataName
not in algo.inpKeys:
276 algo.inpKeys.append(dataName)
279 for inNode, outNode
in self.
dfg.out_edges(algo_name):
284 if dataName
not in algo.outKeys:
285 algo.outKeys.append(dataName)
288 """Assemble the tree of sequencers."""
291 seq = GaudiSequencer(name, ShortCircuit=
False)
293 for n
in self.
cfg[name]:
295 algo_name = n.split(
"/")[1]
if "/" in n
else n
297 if "type" in self.
cfg.nodes[n]:
299 algo_type = self.
cfg.nodes[n].
get(
"type")
303 algo_type = n.split(
"/")[0]
if "/" in n
else "Algorithm"
305 if algo_type
in [
"GaudiSequencer",
"AthSequencer",
"ProcessPhase"]:
306 if algo_name
in [
"RecoITSeq",
"RecoOTSeq",
"RecoTTSeq"]:
317 seq_daughter = GaudiSequencer(algo_name, OutputLevel=INFO)
318 if self.
cfg.nodes[n].
get(
"ModeOR") ==
"True":
320 seq_daughter.ModeOR =
True
323 seq_daughter.ShortCircuit =
False
324 if seq_daughter
not in seq.Members:
325 seq.Members += [seq_daughter]
341 algo_daughter = CPUCruncher(
345 varRuntime=varRuntime,
346 avgRuntime=avgRuntime,
355 if algo_daughter
not in seq.Members:
356 seq.Members += [algo_daughter]