CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
EnableFloatingPointExceptions.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Services
4 // Class : EnableFloatingPointExceptions
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: E. Sexton-Kennedy
10 // Created: Tue Apr 11 13:43:16 CDT 2006
11 //
12 
21 
22 #include <cassert>
23 #include <fenv.h>
24 #include <vector>
25 #ifdef __linux__
26 #include <fpu_control.h>
27 #else
28 #ifdef __APPLE__
29 //TAKEN FROM
30 // http://public.kitware.com/Bug/file_download.php?file_id=3215&type=bug
31 static int
32 fegetexcept (void)
33 {
34  static fenv_t fenv;
35 
36  return fegetenv (&fenv) ? -1 : (fenv.__control & FE_ALL_EXCEPT);
37 }
38 
39 static int
40 feenableexcept (unsigned int excepts)
41 {
42  static fenv_t fenv;
43  unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
44  old_excepts; // previous masks
45 
46  if ( fegetenv (&fenv) ) return -1;
47  old_excepts = fenv.__control & FE_ALL_EXCEPT;
48 
49  // unmask
50  fenv.__control &= ~new_excepts;
51  fenv.__mxcsr &= ~(new_excepts << 7);
52 
53  return ( fesetenv (&fenv) ? -1 : old_excepts );
54 }
55 
56 static int
57 fedisableexcept (unsigned int excepts)
58 {
59  static fenv_t fenv;
60  unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
61  old_excepts; // all previous masks
62 
63  if ( fegetenv (&fenv) ) return -1;
64  old_excepts = fenv.__control & FE_ALL_EXCEPT;
65 
66  // mask
67  fenv.__control |= new_excepts;
68  fenv.__mxcsr |= new_excepts << 7;
69 
70  return ( fesetenv (&fenv) ? -1 : old_excepts );
71 }
72 
73 #endif
74 #endif
75 
76 namespace edm {
77  namespace service {
78 
82  fpuState_(0),
83  defaultState_(0),
84  stateMap_(),
85  stateStack_(),
86  reportSettings_(false) {
87 
88  reportSettings_ = pset.getUntrackedParameter<bool>("reportSettings", false);
89  bool precisionDouble = pset.getUntrackedParameter<bool>("setPrecisionDouble", true);
90 
91  if (reportSettings_) {
92  edm::LogVerbatim("FPE_Enable") << "\nSettings in EnableFloatingPointExceptions constructor";
93  echoState();
94  }
95 
97 
101 
102  setPrecision(precisionDouble);
103 
104  // Note that we must watch all of the transitions even if there are no module specific settings.
105  // This is because the floating point environment may be modified by code outside of this service.
107 
112 
117 
122 
125  }
126 
127  // Establish an environment for each module; default is handled specially.
128  void
130 
131  // Scan the module name list and set per-module values. Be careful to treat
132  // any user-specified default first. If there is one, use it to override our default.
133  // Then remove it from the list so we don't see it again while handling everything else.
134 
135  typedef std::vector<std::string> VString;
136 
137  std::string const def("default");
138  ParameterSet const empty_PSet;
139  VString const empty_VString;
140  VString moduleNames = pset.getUntrackedParameter<VString>("moduleNames", empty_VString);
141 
142  for (VString::const_iterator it(moduleNames.begin()), itEnd = moduleNames.end(); it != itEnd; ++it) {
143  ParameterSet const& modulePSet = pset.getUntrackedParameterSet(*it, empty_PSet);
144  bool enableDivByZeroEx = modulePSet.getUntrackedParameter<bool>("enableDivByZeroEx", false);
145  bool enableInvalidEx = modulePSet.getUntrackedParameter<bool>("enableInvalidEx", false);
146  bool enableOverFlowEx = modulePSet.getUntrackedParameter<bool>("enableOverFlowEx", false);
147  bool enableUnderFlowEx = modulePSet.getUntrackedParameter<bool>("enableUnderFlowEx", false);
148 
149  fpu_flags_type flags = 0;
150  if (enableDivByZeroEx) flags |= FE_DIVBYZERO;
151  if (enableInvalidEx) flags |= FE_INVALID;
152  if (enableOverFlowEx) flags |= FE_OVERFLOW;
153  if (enableUnderFlowEx) flags |= FE_UNDERFLOW;
154  enableAndDisableExcept(flags);
155 
156  fpuState_ = fegetexcept();
157  assert(flags == fpuState_);
158 
159  if (reportSettings_) {
160  edm::LogVerbatim("FPE_Enable") << "\nSettings for module " << *it;
161  echoState();
162  }
163  if (*it == def) {
165  }
166  else {
167  stateMap_[*it] = fpuState_;
168  }
169  }
170  }
171 
172  void
174 
175  if (reportSettings_) {
176  edm::LogVerbatim("FPE_Enable") << "\nSettings after endJob ";
177  echoState();
178  }
179  }
180 
181  void
184  preActions(description, "beginJob");
185  }
186 
187  void
190  postActions(description, "beginJob");
191  }
192 
193  void
196  preActions(description, "endJob");
197  }
198 
199  void
202  postActions(description, "endJob");
203  }
204 
205  void
208  preActions(description, "beginRun");
209  }
210 
211  void
214  postActions(description, "beginRun");
215  }
216 
217  void
220  preActions(description, "endRun");
221  }
222 
223  void
226  postActions(description, "endRun");
227  }
228 
229  void
232  preActions(description, "beginLumi");
233  }
234 
235  void
238  postActions(description, "beginLumi");
239  }
240 
241  void
244  preActions(description, "endLumi");
245  }
246 
247  void
250  postActions(description, "endLumi");
251  }
252 
253  void
256  preActions(description, "event");
257  }
258 
259  void
262  postActions(description, "event");
263  }
264 
265  void
269 
270  desc.addUntracked<bool>("reportSettings", false)->setComment(
271  "Log FPE settings at different phases of the job."
272  );
273  desc.addUntracked<bool>("setPrecisionDouble", true)->setComment(
274  "Set the FPU to use double precision");
275 
277  validator.setComment("FPU exceptions to enable/disable for the requested module");
278  validator.addUntracked<bool>("enableDivByZeroEx", false)->setComment(
279  "Enable/disable exception for 'divide by zero'");
280  validator.addUntracked<bool>("enableInvalidEx", false)->setComment(
281  "Enable/disable exception for 'invalid' math operations (e.g. sqrt(-1))");
282  validator.addUntracked<bool>("enableOverFlowEx", false)->setComment(
283  "Enable/disable exception for numeric 'overflow' (value to big for type)");
284  validator.addUntracked<bool>("enableUnderFlowEx", false)->setComment(
285  "Enable/disable exception for numeric 'underflow' (value to small to be represented accurately)");
286 
287  edm::AllowedLabelsDescription<edm::ParameterSetDescription> node("moduleNames", validator, false);
288  node.setComment("Contains the names for PSets where the PSet name matches the label of a module for which you want to modify the FPE");
289  desc.addNode(node);
290 
291  descriptions.add("EnableFloatingPointExceptions", desc);
292  descriptions.setComment("This service allows you to control the FPU and its exceptions on a per module basis.");
293  }
294 
295 
296  void
299  char const* debugInfo) {
300 
301  // On entry to a module, find the desired state of the fpu and set it
302  // accordingly. Note that any module whose label does not appear in
303  // our list gets the default settings.
304 
305  std::string const& moduleLabel = description.moduleLabel();
306  std::map<std::string, fpu_flags_type>::const_iterator iModule = stateMap_.find(moduleLabel);
307 
308  if (iModule == stateMap_.end()) {
310  }
311  else {
312  fpuState_ = iModule->second;
313  }
315  stateStack_.push(fpuState_);
316 
317  if (reportSettings_) {
318  edm::LogVerbatim("FPE_Enable")
319  << "\nSettings for module label \""
320  << moduleLabel
321  << "\" before "
322  << debugInfo;
323  echoState();
324  }
325  }
326 
327  void
329  postActions(ModuleDescription const& description, char const* debugInfo) {
330  // On exit from a module, set the state of the fpu back to what
331  // it was before entry
332  stateStack_.pop();
333  fpuState_ = stateStack_.top();
335 
336  if (reportSettings_) {
337  edm::LogVerbatim("FPE_Enable")
338  << "\nSettings for module label \""
339  << description.moduleLabel()
340  << "\" after "
341  << debugInfo;
342  echoState();
343  }
344  }
345 
346  void
348 #ifdef __linux__
349 #ifdef __i386__
350  if (precisionDouble) {
351  fpu_control_t cw;
352  _FPU_GETCW(cw);
353 
354  cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
355  _FPU_SETCW(cw);
356  }
357 #endif
358 #endif
359  }
360 
361  void
363  feclearexcept(FE_ALL_EXCEPT);
364  fpu_flags_type current = fegetexcept();
365  fpu_flags_type exceptionsToModify = current ^ target;
366  fpu_flags_type exceptionsToEnable = 0;
367  fpu_flags_type exceptionsToDisable = 0;
368 
369  if (exceptionsToModify & FE_DIVBYZERO) {
370  if (target & FE_DIVBYZERO) {
371  exceptionsToEnable |= FE_DIVBYZERO;
372  }
373  else {
374  exceptionsToDisable |= FE_DIVBYZERO;
375  }
376  }
377  if (exceptionsToModify & FE_INVALID) {
378  if (target & FE_INVALID) {
379  exceptionsToEnable |= FE_INVALID;
380  }
381  else {
382  exceptionsToDisable |= FE_INVALID;
383  }
384  }
385  if (exceptionsToModify & FE_OVERFLOW) {
386  if (target & FE_OVERFLOW) {
387  exceptionsToEnable |= FE_OVERFLOW;
388  }
389  else {
390  exceptionsToDisable |= FE_OVERFLOW;
391  }
392  }
393  if (exceptionsToModify & FE_UNDERFLOW) {
394  if (target & FE_UNDERFLOW) {
395  exceptionsToEnable |= FE_UNDERFLOW;
396  }
397  else {
398  exceptionsToDisable |= FE_UNDERFLOW;
399  }
400  }
401  if (exceptionsToEnable != 0) {
402  feenableexcept(exceptionsToEnable);
403  }
404  if (exceptionsToDisable != 0) {
405  fedisableexcept(exceptionsToDisable);
406  }
407  }
408 
409  void
411  feclearexcept(FE_ALL_EXCEPT);
412  fpu_flags_type femask = fegetexcept();
413  edm::LogVerbatim("FPE_Enable") << "Floating point exception mask is "
414  << std::showbase << std::hex << femask;
415 
416  if (femask & FE_DIVBYZERO)
417  edm::LogVerbatim("FPE_Enable") << "\tDivByZero exception is on";
418  else
419  edm::LogVerbatim("FPE_Enable") << "\tDivByZero exception is off";
420 
421  if (femask & FE_INVALID)
422  edm::LogVerbatim("FPE_Enable") << "\tInvalid exception is on";
423  else
424  edm::LogVerbatim("FPE_Enable") << "\tInvalid exception is off";
425 
426  if (femask & FE_OVERFLOW)
427  edm::LogVerbatim("FPE_Enable") << "\tOverFlow exception is on";
428  else
429  edm::LogVerbatim("FPE_Enable") << "\tOverflow exception is off";
430 
431  if (femask & FE_UNDERFLOW)
432  edm::LogVerbatim("FPE_Enable") << "\tUnderFlow exception is on";
433  else
434  edm::LogVerbatim("FPE_Enable") << "\tUnderFlow exception is off";
435  }
436 
437  } // namespace edm
438 } // namespace service
void preModuleEndRun(ModuleDescription const &description)
void setComment(std::string const &value)
T getUntrackedParameter(std::string const &, T const &) const
void watchPostModuleBeginLumi(PostModuleBeginLumi::slot_type const &iSlot)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void watchPostEndJob(PostEndJob::slot_type const &iSlot)
void postModuleEndLumi(ModuleDescription const &description)
void watchPostModule(PostModule::slot_type const &iSlot)
ParameterDescriptionNode * addNode(ParameterDescriptionNode const &node)
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
void postModuleEndRun(ModuleDescription const &description)
void postModuleBeginJob(ModuleDescription const &description)
void watchPreModuleEndLumi(PreModuleEndLumi::slot_type const &iSlot)
std::string const & moduleLabel() const
void preModuleEndJob(ModuleDescription const &description)
tuple node
Definition: Node.py:50
void watchPreModule(PreModule::slot_type const &iSlot)
void preModuleBeginJob(ModuleDescription const &description)
void setComment(std::string const &value)
void watchPreModuleEndRun(PreModuleEndRun::slot_type const &iSlot)
void postActions(ModuleDescription const &description, char const *debugInfo)
void postModuleBeginLumi(ModuleDescription const &description)
std::map< std::string, fpu_flags_type > stateMap_
ParameterSet const & getUntrackedParameterSet(std::string const &name, ParameterSet const &defaultValue) const
void watchPostModuleEndRun(PostModuleEndRun::slot_type const &iSlot)
void watchPreModuleEndJob(PreModuleEndJob::slot_type const &iSlot)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void preModuleBeginLumi(ModuleDescription const &description)
void watchPreModuleBeginJob(PreModuleBeginJob::slot_type const &iSlot)
void watchPostModuleBeginRun(PostModuleBeginRun::slot_type const &iSlot)
void setComment(std::string const &value)
tuple description
Definition: idDealer.py:66
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void postModule(ModuleDescription const &description)
void preModuleBeginRun(ModuleDescription const &description)
void preModule(ModuleDescription const &description)
void postModuleBeginRun(ModuleDescription const &description)
void watchPostModuleBeginJob(PostModuleBeginJob::slot_type const &iSlot)
void preModuleEndLumi(ModuleDescription const &description)
static Interceptor::Registry registry("Interceptor")
void watchPreModuleBeginLumi(PreModuleBeginLumi::slot_type const &iSlot)
JetCorrectorParameters::Definitions def
Definition: classes.h:10
void postModuleEndJob(ModuleDescription const &description)
void watchPostModuleEndJob(PostModuleEndJob::slot_type const &iSlot)
void watchPreModuleBeginRun(PreModuleBeginRun::slot_type const &iSlot)
void watchPostModuleEndLumi(PostModuleEndLumi::slot_type const &iSlot)
void preActions(ModuleDescription const &description, char const *debugInfo)
EnableFloatingPointExceptions(ParameterSet const &pset, ActivityRegistry &registry)
const std::string * moduleLabel() const
Definition: HLTadd.h:40