Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / utility / gmxomp.h
index c698b5168ac11fce1c9caddf58af10568f577caa..553eadc09294483bc5555c83eecbb11e7f4bed7c 100644 (file)
 #ifndef GMX_UTILITY_OMP_H
 #define GMX_UTILITY_OMP_H
 
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
+#include <stdio.h>
+
+#ifndef GMX_NATIVE_WINDOWS
 /* Ugly hack because the openmp implementation below hacks into the SIMD
  * settings to decide when to use _mm_pause(). This should eventually be
  * changed into proper detection of the intrinsics uses, not SIMD.
     (defined GMX_SIMD_X86_AVX2_256)
 #    include <xmmintrin.h>
 #endif
+#else
+#include <windows.h>
+#endif
 
-#include "types/commrec.h"
-#include "mdrun.h"
+#include "gromacs/utility/basedefinitions.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -109,22 +112,45 @@ void gmx_omp_set_num_threads(int num_threads);
 /*! \brief
  * Check for externally set thread affinity to avoid conflicts with \Gromacs
  * internal setting.
+ *
+ * \param[out] message  Receives the message to be shown to the user.
+ * \returns `true` if we can set thread affinity ourselves.
+ *
+ * While GNU OpenMP does not set affinity by default, the Intel OpenMP library
+ * does.  This conflicts with the internal affinity (especially thread-MPI)
+ * setting, results in incorrectly locked threads, and causes dreadful performance.
+ *
+ * The KMP_AFFINITY environment variable is used by Intel, GOMP_CPU_AFFINITY
+ * by the GNU compilers (Intel also honors it well).  If any of the variables
+ * is set, we should honor it and disable the internal pinning.
+ * When using Intel OpenMP, we will disable affinity if the user did not set it
+ * manually through one of the aforementioned environment variables.
+ *
+ * Note that the Intel OpenMP affinity disabling will only take effect if this
+ * function is called before the OpenMP library gets initialized, which happens
+ * when the first call is made into a compilation unit that contains OpenMP
+ * pragmas.
+ *
+ * If this function returns `false`, the caller is responsible to disable the
+ * pinning, show the message from \p *message to the user, and free the memory
+ * allocated for \p *message.
+ * If the return value is `true`, \p *message is NULL.
  */
-void gmx_omp_check_thread_affinity(FILE *fplog, const t_commrec *cr,
-                                   gmx_hw_opt_t *hw_opt);
+gmx_bool gmx_omp_check_thread_affinity(char **message);
 
 /*! \brief
  * Pause for use in a spin-wait loop.
  */
 static gmx_inline void gmx_pause()
 {
+#ifndef _MSC_VER
     /* Ugly hack because the openmp implementation below hacks into the SIMD
      * settings to decide when to use _mm_pause(). This should eventually be
      * changed into proper detection of the intrinsics uses, not SIMD.
      */
-#if (defined GMX_SIMD_X86_SSE2) || (defined GMX_SIMD_X86_SSE4_1) || \
+#if ((defined GMX_SIMD_X86_SSE2) || (defined GMX_SIMD_X86_SSE4_1) || \
     (defined GMX_SIMD_X86_AVX_128_FMA) || (defined GMX_SIMD_X86_AVX_256) || \
-    (defined GMX_SIMD_X86_AVX2_256)
+    (defined GMX_SIMD_X86_AVX2_256)) && !defined(__MINGW32__)
     /* Replace with tbb::internal::atomic_backoff when/if we use TBB */
     _mm_pause();
 #elif defined __MIC__
@@ -132,6 +158,9 @@ static gmx_inline void gmx_pause()
 #else
     /* No wait for unknown architecture */
 #endif
+#else
+    YieldProcessor();
+#endif
 }
 
 /*! \} */