Belle II Software  release-05-02-19
EventInfoSetterModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Andreas Moll *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <framework/modules/core/EventInfoSetterModule.h>
12 
13 #include <framework/core/Environment.h>
14 #include <framework/utilities/Utils.h>
15 
16 #include <chrono>
17 #include <set>
18 
19 using namespace std;
20 using namespace Belle2;
21 
22 //-----------------------------------------------------------------
23 // Register the Module
24 //-----------------------------------------------------------------
25 REG_MODULE(EventInfoSetter)
26 
27 //-----------------------------------------------------------------
28 // Implementation
29 //-----------------------------------------------------------------
30 
32 {
33  if (getenv("BELLE2_PRODUCTION"))
34  m_production = stoi(getenv("BELLE2_PRODUCTION"));
35 
36  //Set module properties
37  setDescription(
38  "Sets the event meta data information (exp, run, evt). You must use this "
39  "module to tell basf2 about the number of events you want to generate, "
40  "unless you have an input module that already does so. Note that all "
41  "experiment/run combinations specified must be unique."
42  );
43 
44  //Parameter definition
45  addParam("expList", m_expList, "List of experiment numbers. Can be overridden via --experiment argument to basf2.", m_expList);
46  addParam("runList", m_runList, "List of run numbers. Can be overridden via --run argument to basf2.", m_runList);
47  addParam("evtNumList", m_evtNumList, "List of the number of events which "
48  "should be processed. Can be overridden via -n argument to basf2.",
49  m_evtNumList);
50  addParam("skipNEvents", m_eventsToSkip, "Skip this number of events before "
51  "starting. Equivalent to running over this many events without performing "
52  "any action, to allow starting at higher event numbers.", m_eventsToSkip);
53  addParam("skipToEvent", m_skipToEvent, "Skip events until the event with "
54  "the specified (experiment, run, event number) occurs. This parameter "
55  "is useful for debugging to start with a specific event.", m_skipToEvent);
56 }
57 
58 EventInfoSetterModule::~EventInfoSetterModule() = default;
59 
60 void EventInfoSetterModule::initialize()
61 {
62  //Register the EventMetaData in the data store
63  m_eventMetaDataPtr.registerInDataStore(DataStore::c_ErrorIfAlreadyRegistered);
64 
65  //steering file content overwritten via command line arguments?
66  unsigned int numEventsArgument = Environment::Instance().getNumberEventsOverride();
67  int runOverride = Environment::Instance().getRunOverride();
68  int expOverride = Environment::Instance().getExperimentOverride();
69  if (numEventsArgument > 0 or runOverride >= 0 or expOverride >= 0) {
70  if (m_evtNumList.size() > 1) {
71  B2ERROR("The -n/--events, --run, and --experiment options cannot be used when multiple runs are specified for EventInfoSetter!");
72  }
73  m_evtNumList[0] = numEventsArgument;
74  if (runOverride >= 0)
75  m_runList[0] = runOverride;
76  if (expOverride >= 0)
77  m_expList[0] = expOverride;
78  }
79 
80  unsigned int skipNEventsOverride = Environment::Instance().getSkipEventsOverride();
81  if (skipNEventsOverride != 0)
82  m_eventsToSkip = skipNEventsOverride;
83 
84  //Make sure all lists have the same size
85  unsigned int defListSize = m_expList.size();
86  if ((m_runList.size() != defListSize) || (m_evtNumList.size() != defListSize)) {
87  B2ERROR("Parameters are inconsistent. The exp, run and evt lists must have the same number of entries.");
88  } else if (defListSize == 0) {
89  B2ERROR("There are no events to be processed!");
90  } else {
91  set<pair<int, int>> expRunSet;
92  for (unsigned int i = 0; i < defListSize; i++) {
93  auto ret = expRunSet.insert(make_pair(m_expList[i], m_runList[i]));
94  if (!ret.second) {
95  B2ERROR("Exp " << ret.first->first << ", run " << ret.first->second <<
96  " used more than once! Please make sure all experiment/run combinations are unique.");
97  }
98  if (m_expList[i] < 0 or m_expList[i] > 1023)
99  B2ERROR("Experiment " << m_expList[i] << " is out of range, should be in [0, 1023]!");
100  if (m_runList[i] < 0)
101  B2ERROR("Run " << m_runList[i] << " is out of range, should be >= 0!");
102  unsigned int nevents = m_evtNumList[i];
103  if (nevents == std::numeric_limits<unsigned int>::max()) {
104  B2ERROR("Invalid number of events (valid range: 0.." << std::numeric_limits<unsigned int>::max() - 1 << ")!");
105  }
106  }
107  }
108 
109  if (!m_skipToEvent.empty()) {
110  // make sure the number of entries is exactly 3
111  if (m_skipToEvent.size() != 3) {
112  B2ERROR("skipToEvent must be a list of three values: experiment, run, event number");
113  // ignore the value
114  m_skipToEvent.clear();
115  }
116  if (m_eventsToSkip > 0) {
117  B2ERROR("You cannot supply a number of events to skip (skipNEvents) and an "
118  "event to skip to (skipToEvent) at the same time, ignoring skipNEvents");
119  //force the number of skipped events to be zero
120  m_eventsToSkip = 0;
121  }
122  }
123 
124  m_evtNumber = 1;
125  m_colIndex = 0; //adjusted in event() if mismatched
126 
127  //determine number of events we will process
128  unsigned int totalevents = 0;
129  Belle2::EventInfoSetterModule copy(*this);
130  while (copy.advanceEventCounter()) {
131  copy.m_evtNumber++;
132  totalevents++;
133  }
134  B2DEBUG(100, "EventInfoSetter: will process " << totalevents << " events in total.");
135 
136  Environment::Instance().setNumberOfMCEvents(totalevents);
137 }
138 
139 
140 bool EventInfoSetterModule::advanceEventCounter()
141 {
142  // optimized for the assumed normal case of few runs with lots of events
143  // and no skipping.
144  // In the case of 1e9 events, the branch prediction hints give the following
145  // improvements:
146  // clang: -18% real time
147  // gcc (opt): -52% real time
148  while (true) {
149  if (branch_unlikely(m_evtNumber > m_evtNumList[m_colIndex])) {
150 
151  //Search for a column where the event number is greater than 0.
152  do {
153  m_colIndex++;
154  } while ((m_colIndex < static_cast<int>(m_expList.size())) &&
155  (m_evtNumList[m_colIndex] == 0));
156 
157  if (m_colIndex < static_cast<int>(m_expList.size())) {
158  m_evtNumber = 1;
159  } else { //no experiment/run with non-zero number of events found
160  return false;
161  }
162  }
163 
164  // check if we want to skip to a specific event
165  if (branch_unlikely(!m_skipToEvent.empty())) {
166  // if current experiment and run number is different to what we're looking for
167  if (m_skipToEvent[0] != m_expList[m_colIndex] || m_skipToEvent[1] != m_runList[m_colIndex]) {
168  // then we set the m_evtNumber to the max+1
169  m_evtNumber = m_evtNumList[m_colIndex] + 1;
170  } else {
171  // otherwise we start at the event number we want to skip to
172  m_evtNumber = m_skipToEvent[2];
173  // and reset the variable as skipping is done
174  m_skipToEvent.clear();
175  }
176  // and check again if the event number is in the range we want to generate
177  } else if (branch_unlikely(m_eventsToSkip != 0)) { //are we still skipping?
178  unsigned int nskip = 1;
179  const unsigned int eventsInList = m_evtNumList[m_colIndex];
180  if (m_evtNumber <= eventsInList) //skip to end of current run?
181  nskip = eventsInList - m_evtNumber + 1;
182  if (nskip > m_eventsToSkip)
183  nskip = m_eventsToSkip;
184 
185  m_eventsToSkip -= nskip;
186  m_evtNumber += nskip;
187  } else {
188  break;
189  }
190  }
191  return true;
192 }
193 
194 void EventInfoSetterModule::event()
195 {
196  if (!advanceEventCounter())
197  return;
198 
199  m_eventMetaDataPtr.create();
200  m_eventMetaDataPtr->setProduction(m_production);
201  m_eventMetaDataPtr->setExperiment(m_expList[m_colIndex]);
202  m_eventMetaDataPtr->setRun(m_runList[m_colIndex]);
203  m_eventMetaDataPtr->setEvent(m_evtNumber);
204  auto time = std::chrono::high_resolution_clock::now().time_since_epoch();
205  m_eventMetaDataPtr->setTime(std::chrono::duration_cast<std::chrono::nanoseconds>(time).count());
206 
207  m_evtNumber++;
208 }
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
branch_unlikely
#define branch_unlikely(x)
A macro to tell the compiler that the argument x will be very likely be false.
Definition: Utils.h:148
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::EventInfoSetterModule
Module to set event, run, experiment numbers.
Definition: EventInfoSetterModule.h:44