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 
14 
22 
23 #include <cassert>
24 #include <fenv.h>
25 #include <vector>
26 #ifdef __linux__
27 #include <fpu_control.h>
28 #else
29 #ifdef __APPLE__
30 //TAKEN FROM
31 // http://public.kitware.com/Bug/file_download.php?file_id=3215&type=bug
32 static int
33 fegetexcept (void) {
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  static fenv_t fenv;
42  unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
43  old_excepts; // previous masks
44 
45  if(fegetenv (&fenv)) return -1;
46  old_excepts = fenv.__control & FE_ALL_EXCEPT;
47 
48  // unmask
49  fenv.__control &= ~new_excepts;
50  fenv.__mxcsr &= ~(new_excepts << 7);
51 
52  return (fesetenv (&fenv) ? -1 : old_excepts);
53 }
54 
55 static int
56 fedisableexcept (unsigned int excepts) {
57  static fenv_t fenv;
58  unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
59  old_excepts; // all previous masks
60 
61  if(fegetenv (&fenv)) return -1;
62  old_excepts = fenv.__control & FE_ALL_EXCEPT;
63 
64  // mask
65  fenv.__control |= new_excepts;
66  fenv.__mxcsr |= new_excepts << 7;
67 
68  return (fesetenv (&fenv) ? -1 : old_excepts);
69 }
70 
71 #endif
72 #endif
73 
74 namespace edm {
75  namespace service {
76 
80  fpuState_(0),
81  defaultState_(0),
82  stateMap_(),
83  stateStack_(),
84  reportSettings_(false) {
85 
86  reportSettings_ = pset.getUntrackedParameter<bool>("reportSettings", false);
87  bool precisionDouble = pset.getUntrackedParameter<bool>("setPrecisionDouble", true);
88 
89  if(reportSettings_) {
90  LogVerbatim("FPE_Enable") << "\nSettings in EnableFloatingPointExceptions constructor";
91  echoState();
92  }
93 
95 
99 
100  setPrecision(precisionDouble);
101 
102  // Note that we must watch all of the transitions even if there are no module specific settings.
103  // This is because the floating point environment may be modified by code outside of this service.
105 
110 
115 
120 
123  }
124 
125  // Establish an environment for each module; default is handled specially.
126  void
128 
129  // Scan the module name list and set per-module values. Be careful to treat
130  // any user-specified default first. If there is one, use it to override our default.
131  // Then remove it from the list so we don't see it again while handling everything else.
132 
133  typedef std::vector<std::string> VString;
134 
135  std::string const def("default");
136  ParameterSet const empty_PSet;
137  VString const empty_VString;
138  VString moduleNames = pset.getUntrackedParameter<VString>("moduleNames", empty_VString);
139 
140  for(VString::const_iterator it(moduleNames.begin()), itEnd = moduleNames.end(); it != itEnd; ++it) {
141  ParameterSet const& modulePSet = pset.getUntrackedParameterSet(*it, empty_PSet);
142  bool enableDivByZeroEx = modulePSet.getUntrackedParameter<bool>("enableDivByZeroEx", false);
143  bool enableInvalidEx = modulePSet.getUntrackedParameter<bool>("enableInvalidEx", false);
144  bool enableOverFlowEx = modulePSet.getUntrackedParameter<bool>("enableOverFlowEx", false);
145  bool enableUnderFlowEx = modulePSet.getUntrackedParameter<bool>("enableUnderFlowEx", false);
146 
147  fpu_flags_type flags = 0;
148  if(enableDivByZeroEx) flags |= FE_DIVBYZERO;
149  if(enableInvalidEx) flags |= FE_INVALID;
150  if(enableOverFlowEx) flags |= FE_OVERFLOW;
151  if(enableUnderFlowEx) flags |= FE_UNDERFLOW;
152  enableAndDisableExcept(flags);
153 
154  fpuState_ = fegetexcept();
155  assert(flags == fpuState_);
156 
157  if(reportSettings_) {
158  LogVerbatim("FPE_Enable") << "\nSettings for module " << *it;
159  echoState();
160  }
161  if(*it == def) {
163  }
164  else {
165  stateMap_[*it] = fpuState_;
166  }
167  }
168  }
169 
170  void
172 
173  if(reportSettings_) {
174  LogVerbatim("FPE_Enable") << "\nSettings after endJob ";
175  echoState();
176  }
177  }
178 
179  void
182  preActions(description, "beginJob");
183  }
184 
185  void
188  postActions(description, "beginJob");
189  }
190 
191  void
194  preActions(description, "endJob");
195  }
196 
197  void
200  postActions(description, "endJob");
201  }
202 
203  void
206  preActions(description, "beginRun");
207  }
208 
209  void
212  postActions(description, "beginRun");
213  }
214 
215  void
218  preActions(description, "endRun");
219  }
220 
221  void
224  postActions(description, "endRun");
225  }
226 
227  void
230  preActions(description, "beginLumi");
231  }
232 
233  void
236  postActions(description, "beginLumi");
237  }
238 
239  void
242  preActions(description, "endLumi");
243  }
244 
245  void
248  postActions(description, "endLumi");
249  }
250 
251  void
254  preActions(description, "event");
255  }
256 
257  void
260  postActions(description, "event");
261  }
262 
263  void
267 
268  desc.addUntracked<bool>("reportSettings", false)->setComment(
269  "Log FPE settings at different phases of the job.");
270  desc.addUntracked<bool>("setPrecisionDouble", true)->setComment(
271  "Set the FPU to use double precision");
272 
273  ParameterSetDescription validator;
274  validator.setComment("FPU exceptions to enable/disable for the requested module");
275  validator.addUntracked<bool>("enableDivByZeroEx", false)->setComment(
276  "Enable/disable exception for 'divide by zero'");
277  validator.addUntracked<bool>("enableInvalidEx", false)->setComment(
278  "Enable/disable exception for 'invalid' math operations (e.g. sqrt(-1))");
279  validator.addUntracked<bool>("enableOverFlowEx", false)->setComment(
280  "Enable/disable exception for numeric 'overflow' (value to big for type)");
281  validator.addUntracked<bool>("enableUnderFlowEx", false)->setComment(
282  "Enable/disable exception for numeric 'underflow' (value to small to be represented accurately)");
283 
284  AllowedLabelsDescription<ParameterSetDescription> node("moduleNames", validator, false);
285  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");
286  desc.addNode(node);
287 
288  descriptions.add("EnableFloatingPointExceptions", desc);
289  descriptions.setComment("This service allows you to control the FPU and its exceptions on a per module basis.");
290  }
291 
292 
293  void
296  char const* debugInfo) {
297 
298  // On entry to a module, find the desired state of the fpu and set it
299  // accordingly. Note that any module whose label does not appear in
300  // our list gets the default settings.
301 
302  std::string const& moduleLabel = description.moduleLabel();
303  std::map<std::string, fpu_flags_type>::const_iterator iModule = stateMap_.find(moduleLabel);
304 
305  if(iModule == stateMap_.end()) {
307  }
308  else {
309  fpuState_ = iModule->second;
310  }
312  stateStack_.push(fpuState_);
313 
314  if(reportSettings_) {
315  LogVerbatim("FPE_Enable")
316  << "\nSettings for module label \""
317  << moduleLabel
318  << "\" before "
319  << debugInfo;
320  echoState();
321  }
322  }
323 
324  void
326  postActions(ModuleDescription const& description, char const* debugInfo) {
327  // On exit from a module, set the state of the fpu back to what
328  // it was before entry
329  stateStack_.pop();
330  fpuState_ = stateStack_.top();
332 
333  if(reportSettings_) {
334  LogVerbatim("FPE_Enable")
335  << "\nSettings for module label \""
336  << description.moduleLabel()
337  << "\" after "
338  << debugInfo;
339  echoState();
340  }
341  }
342 
343 #ifdef __linux__
344 #ifdef __i386__
345  void
346  EnableFloatingPointExceptions::setPrecision(bool precisionDouble) {
347  if(precisionDouble) {
348  fpu_control_t cw;
349  _FPU_GETCW(cw);
350 
351  cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
352  _FPU_SETCW(cw);
353  }
354  }
355 #else
356  void
357  EnableFloatingPointExceptions::setPrecision(bool /*precisionDouble*/) {
358  }
359 #endif
360 #else
361  void
363  }
364 #endif
365 
366  void
368  feclearexcept(FE_ALL_EXCEPT);
369  fpu_flags_type current = fegetexcept();
370  fpu_flags_type exceptionsToModify = current ^ target;
371  fpu_flags_type exceptionsToEnable = 0;
372  fpu_flags_type exceptionsToDisable = 0;
373 
374  if(exceptionsToModify & FE_DIVBYZERO) {
375  if(target & FE_DIVBYZERO) {
376  exceptionsToEnable |= FE_DIVBYZERO;
377  }
378  else {
379  exceptionsToDisable |= FE_DIVBYZERO;
380  }
381  }
382  if(exceptionsToModify & FE_INVALID) {
383  if(target & FE_INVALID) {
384  exceptionsToEnable |= FE_INVALID;
385  }
386  else {
387  exceptionsToDisable |= FE_INVALID;
388  }
389  }
390  if(exceptionsToModify & FE_OVERFLOW) {
391  if(target & FE_OVERFLOW) {
392  exceptionsToEnable |= FE_OVERFLOW;
393  }
394  else {
395  exceptionsToDisable |= FE_OVERFLOW;
396  }
397  }
398  if(exceptionsToModify & FE_UNDERFLOW) {
399  if(target & FE_UNDERFLOW) {
400  exceptionsToEnable |= FE_UNDERFLOW;
401  }
402  else {
403  exceptionsToDisable |= FE_UNDERFLOW;
404  }
405  }
406  if(exceptionsToEnable != 0) {
407  feenableexcept(exceptionsToEnable);
408  }
409  if(exceptionsToDisable != 0) {
410  fedisableexcept(exceptionsToDisable);
411  }
412  }
413 
414  void
416  feclearexcept(FE_ALL_EXCEPT);
417  fpu_flags_type femask = fegetexcept();
418  LogVerbatim("FPE_Enable") << "Floating point exception mask is "
419  << std::showbase << std::hex << femask;
420 
421  if(femask & FE_DIVBYZERO)
422  LogVerbatim("FPE_Enable") << "\tDivByZero exception is on";
423  else
424  LogVerbatim("FPE_Enable") << "\tDivByZero exception is off";
425 
426  if(femask & FE_INVALID)
427  LogVerbatim("FPE_Enable") << "\tInvalid exception is on";
428  else
429  LogVerbatim("FPE_Enable") << "\tInvalid exception is off";
430 
431  if(femask & FE_OVERFLOW)
432  LogVerbatim("FPE_Enable") << "\tOverFlow exception is on";
433  else
434  LogVerbatim("FPE_Enable") << "\tOverflow exception is off";
435 
436  if(femask & FE_UNDERFLOW)
437  LogVerbatim("FPE_Enable") << "\tUnderFlow exception is on";
438  else
439  LogVerbatim("FPE_Enable") << "\tUnderFlow exception is off";
440  }
441 
442  } // namespace edm
443 } // 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:12
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)