Disable FPEs at end of runner
authorRoland Schulz <roland.schulz@intel.com>
Thu, 19 Jul 2018 16:34:27 +0000 (09:34 -0700)
committerMark Abraham <mark.j.abraham@gmail.com>
Mon, 30 Jul 2018 12:39:18 +0000 (14:39 +0200)
In mdrun unit tests the exceptions enabled for one test were
still active in the next. This caused issues with group
kernel which is known to throw FPEs.

Related #2404

Change-Id: Ie347a29f25ed16836a3164b61c9fca87ca66fc44

src/gromacs/math/utilities.cpp
src/gromacs/math/utilities.h
src/gromacs/mdrun/runner.cpp

index 4cdbae41e49c2071fb7fc65ec54d32d7bc730811..652f1e603e2656993fef6c41d177b73c94b73ef5 100644 (file)
@@ -146,6 +146,28 @@ int gmx_feenableexcept()
 #endif
 }
 
+int gmx_fedisableexcept()
+{
+#if HAVE_FEDISABLEEXCEPT
+    return fedisableexcept(c_FPexceptions);
+#elif (defined(__i386__) || defined(__x86_64__)) && defined(__APPLE__)
+    static fenv_t fenv;
+    unsigned int  new_excepts = c_FPexceptions & FE_ALL_EXCEPT;
+    if (fegetenv (&fenv) )
+    {
+        return -1;
+    }
+
+    // mask
+    fenv.__control |= new_excepts;
+    fenv.__mxcsr   |= new_excepts << 7;
+
+    return fesetenv(&fenv);
+#else
+    return -1;
+#endif
+}
+
 real max_cutoff(real cutoff1, real cutoff2)
 {
     if (cutoff1 == 0 || cutoff2 == 0)
index eba796a91027c48aaf0ce88b541d1bb282201293..a90cb2b6b55bf1b276f077ecddb9a29cd5e57e92 100644 (file)
@@ -167,6 +167,14 @@ gmx_greatest_common_divisor(int p, int q);
  */
 int gmx_feenableexcept();
 
+/*! \brief Disable floating-point exceptions if supported on OS
+ *
+ * Disables division-by-zero, invalid value, and overflow.
+ *
+ * \returns 0 if successful in disabling exceptions, anything else in case of failure/unsupported OS.
+ */
+int gmx_fedisableexcept();
+
 /*! \brief Return cut-off to use
  *
  * Takes the max of two cut-offs. However a cut-off of 0
index 290ddc998fc0e87b6242373075c3a9a282ec35fa..672a93368c0def2232ab8c0bf5be428ad2aaa2ed 100644 (file)
@@ -1377,6 +1377,16 @@ int Mdrunner::mdrunner()
         fplog = nullptr;
     }
 
+    /* Reset FPEs (important for unit tests) by disabling them. Assumes no
+     * exceptions were enabled before function was called. */
+#if !defined NDEBUG && !(defined __clang__ && defined __OPTIMIZE__)
+    if (!EI_TPI(inputrec->eI) &&
+        inputrec->cutoff_scheme == ecutsVERLET)
+    {
+        gmx_fedisableexcept();
+    }
+#endif
+
     rc = (int)gmx_get_stop_condition();
 
 #if GMX_THREAD_MPI