Belle II Software release-09-00-00
benchmark.py
1#!/usr/bin/env python3
2
3
10
11
15
16import basf2 as b2
17from generators import add_kkmc_generator
18from simulation import add_simulation
19from validation_gt import get_validation_globaltags
20from rawdata import add_unpackers
21from reconstruction import add_reconstruction
22from argparse import ArgumentParser
23import os
24import glob
25import sys
26
27# parse command line options
28parser = ArgumentParser(description='Measure the execution time.')
29parser.add_argument('-m', '--multiplicity', default='high', choices=['high', 'low', 'data'], help='Multiplicity or type of events')
30parser.add_argument('-l', '--limits', help='Name of file containing limits')
31parser.add_argument('-f', '--file', help='Name of benchmark output file')
32args = parser.parse_args()
33
34# create path and reduce log level
35main = b2.create_path()
36b2.set_log_level(b2.LogLevel.ERROR)
37
38if args.multiplicity == 'data':
39 # Global Tag needed as these are Raw data
40 b2.conditions.override_globaltags(get_validation_globaltags())
41
42 input_files = glob.glob(os.environ.get('BELLE2_VALIDATION_DATA_DIR', '') + '/rawdata/physics.0010.05095*.root')
43 main.add_module("RootInput", inputFileNames=input_files)
44
45 main.add_module('EventInfoPrinter').set_log_level(b2.LogLevel.INFO)
46
47 # gearbox and geometry
48 main.add_module('Gearbox')
49 main.add_module('Geometry', useDB=True)
50
51 # unpacking
52 add_unpackers(main)
53
54else:
55 # specify number of events to be generated
56 main.add_module('EventInfoSetter', evtNumList=[1000])
57 main.add_module('EventInfoPrinter').set_log_level(b2.LogLevel.INFO)
58
59 if args.multiplicity == 'high':
60 # generate BBbar events if high multiplicity is selected
61 main.add_module('EvtGenInput')
62
63 elif args.multiplicity == 'low':
64 # generate mu pair events if low multiplicity is selected
65 add_kkmc_generator(main, 'mu+mu-')
66
67 # detector and L1 trigger simulation
68 add_simulation(main, bkgfiles=glob.glob(os.environ.get('BELLE2_BACKGROUND_DIR', '/sw/belle2/bkg') + '/*.root'))
69
70# reconstruction
71add_reconstruction(main)
72
73# process events and print call statistics
74b2.process(main)
75print(b2.statistics)
76
77# read limits
78limits = {}
79limits_file = args.limits
80default_limits_file = args.multiplicity + '.limits'
81if limits_file is None and os.path.isfile(default_limits_file):
82 limits_file = default_limits_file
83if limits_file is not None:
84 for line in open(limits_file).readlines():
85 entries = line.split()
86 limits[entries[0]] = float(entries[1])
87 if len(entries) > 2:
88 limits[entries[0]] /= float(entries[2])
89
90# get execution times
91categories = [
92 'Simulation',
93 'TriggerSimulation',
94 'Clustering',
95 'Prefilter_Tracking',
96 'Posttracking_Reconstruction',
97 'Postfilter_Reconstruction']
98times = {}
99for module in b2.statistics.modules:
100 if module.name not in ['Sum_' + category for category in categories]:
101 continue
102 category = module.name[4:]
103 if category not in times.keys():
104 times[category] = 0
105 times[category] += module.time_mean(b2.statistics.EVENT) * 1e-6
106
107# open output file
108output = None
109if args.file is not None:
110 output = open(args.file, 'w')
111
112# print benchmark results and write them to the output file
113b2.set_log_level(b2.LogLevel.INFO)
114max_fraction = -1
115for category in categories:
116 if category not in times.keys():
117 continue
118 time = times[category]
119 message = f'Execution time per event for {category} is {time:.0f} ms'
120 fraction = -1
121 if category in limits.keys():
122 fraction = time / limits[category]
123 if fraction > max_fraction:
124 max_fraction = fraction
125 message += f' = {fraction:.0%} of the limit.'
126 if fraction <= 0.9:
127 b2.B2INFO(message)
128 elif fraction <= 1:
129 b2.B2WARNING(message)
130 else:
131 b2.B2ERROR(message)
132 else:
133 b2.B2INFO(message)
134
135 if output is not None:
136 output.write(f'{category} {time:.2f}')
137 if fraction >= 0:
138 output.write(f' {fraction:.4f}')
139 output.write('\n')
140
141# fail if above limit
142sys.exit(0 if max_fraction <= 1 else 1)