#include "gromacs/utility/fatalerror.h"
#include "typedefs.h"
+#include "types/commrec.h"
#include "macros.h"
#include "network.h"
#include "copyrite.h"
#include "gmx_omp_nthreads.h"
#include "md_logging.h"
#include "gmx_thread_affinity.h"
+#include "network.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxomp.h"
+#include "gromacs/utility/smalloc.h"
static int
get_thread_affinity_layout(FILE *fplog,
* Note that this will only work on Linux as we use a GNU feature.
*/
void
-gmx_check_thread_affinity_set(FILE gmx_unused *fplog,
- const t_commrec gmx_unused *cr,
- gmx_hw_opt_t gmx_unused *hw_opt,
- int gmx_unused ncpus,
- gmx_bool gmx_unused bAfterOpenmpInit)
+gmx_check_thread_affinity_set(FILE *fplog,
+ const t_commrec *cr,
+ gmx_hw_opt_t *hw_opt,
+ int gmx_unused ncpus,
+ gmx_bool bAfterOpenmpInit)
{
#ifdef HAVE_SCHED_GETAFFINITY
cpu_set_t mask_current;
int i, ret, cpu_count, cpu_set;
gmx_bool bAllSet;
+#endif
assert(hw_opt);
+ if (!bAfterOpenmpInit)
+ {
+ /* Check for externally set OpenMP affinity and turn off internal
+ * pinning if any is found. We need to do this check early to tell
+ * thread-MPI whether it should do pinning when spawning threads.
+ * TODO: the above no longer holds, we should move these checks later
+ */
+ if (hw_opt->thread_affinity != threadaffOFF)
+ {
+ char *message;
+ if (!gmx_omp_check_thread_affinity(&message))
+ {
+ /* TODO: with -pin auto we should only warn when using all cores */
+ md_print_warn(cr, fplog, "%s", message);
+ sfree(message);
+ hw_opt->thread_affinity = threadaffOFF;
+ }
+ }
+
+ /* With thread-MPI this is needed as pinning might get turned off,
+ * which needs to be known before starting thread-MPI.
+ * With thread-MPI hw_opt is processed here on the master rank
+ * and passed to the other ranks later, so we only do this on master.
+ */
+ if (!SIMMASTER(cr))
+ {
+ return;
+ }
+#ifndef GMX_THREAD_MPI
+ return;
+#endif
+ }
+
+#ifdef HAVE_SCHED_GETAFFINITY
if (hw_opt->thread_affinity == threadaffOFF)
{
/* internal affinity setting is off, don't bother checking process affinity */
*/
#ifndef GMX_THREAD_AFFINITY_H_
#define GMX_THREAD_AFFINITY_H_
+
#include "typedefs.h"
#ifdef __cplusplus
* made by the OpenMP library.
*
* Note that this will only work on Linux as we use a GNU feature.
+ * With bAfterOpenmpInit false, it will also detect whether OpenMP environment
+ * variables for setting the affinity are set.
*/
void
gmx_check_thread_affinity_set(FILE *fplog, const t_commrec *cr,
#endif
#include <math.h>
+
+#include "types/commrec.h"
#include "main.h"
#include "constr.h"
#include "copyrite.h"
#endif
#include <stdio.h>
+
#include "typedefs.h"
+#include "types/commrec.h"
#include "vsite.h"
#include "macros.h"
#include "gromacs/utility/smalloc.h"
#include <stdlib.h>
#include <string.h>
+#include <exception>
+
#include "thread_mpi/threads.h"
#include "gromacs/legacyheaders/types/commrec.h"
-#include "gromacs/legacyheaders/copyrite.h"
-#include "gromacs/legacyheaders/macros.h"
#include "gromacs/legacyheaders/network.h"
#include "gromacs/fileio/futil.h"
#include "gromacs/fileio/gmxfio.h"
+#include "gromacs/utility/baseversion.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/gmxmpi.h"
+#include "gromacs/utility/programcontext.h"
#include "gromacs/utility/smalloc.h"
static gmx_bool bDebug = FALSE;
gmx_bool bDebugMode(void)
{
- gmx_bool ret;
-#if 0
- tMPI_Thread_mutex_lock(&debug_mutex);
-#endif
- ret = bDebug;
-#if 0
- tMPI_Thread_mutex_unlock(&debug_mutex);
-#endif
return bDebug;
}
const t_commrec *cr, gmx_domdec_t *dd,
const char *fmt, ...)
{
- gmx_bool bFinalize;
va_list ap;
char msg[STRLEN];
#ifdef GMX_MPI
int result;
#endif
- bFinalize = TRUE;
-
#ifdef GMX_MPI
/* Check if we are calling on all processes in MPI_COMM_WORLD */
if (cr != NULL)
MPI_Comm_compare(dd->mpi_comm_all, MPI_COMM_WORLD, &result);
}
/* Any result except MPI_UNEQUAL allows us to call MPI_Finalize */
- bFinalize = (result != MPI_UNEQUAL);
+ const bool bFinalize = (result != MPI_UNEQUAL);
+#else
+ const bool bFinalize = true;
#endif
if ((cr != NULL && MASTER(cr) ) ||
{ "input", "Input error or input inconsistency" },
{ "mem", "Memory allocation/freeing error" },
{ "open", "Can not open file" },
- { "range", "Range checking error" }
+ { "range", "Range checking error" },
+ { NULL, NULL}
};
-#define NMSG asize(msg)
- char buf[1024];
- size_t i;
if (key == NULL)
{
}
else
{
- for (i = 0; (i < NMSG); i++)
+ for (size_t i = 0; msg[i].key != NULL; ++i)
{
if (strcmp(key, msg[i].key) == 0)
{
- break;
+ return strdup(msg[i].msg);
}
}
- if (i == NMSG)
- {
- sprintf(buf, "No error message associated with key %s\n%s", key, gmxuser);
- return strdup(buf);
- }
- else
- {
- return strdup(msg[i].msg);
- }
+ char buf[1024];
+ sprintf(buf, "No error message associated with key %s\n%s", key, gmxuser);
+ return strdup(buf);
}
}
{
sprintf(errerrbuf, "Empty fatal_error message. %s", gmxuser);
}
+ // In case ProgramInfo is not initialized and there is an issue with the
+ // initialization, fall back to "GROMACS".
+ const char *programName = "GROMACS";
+ try
+ {
+ programName = gmx::getProgramContext().displayName();
+ }
+ catch (const std::exception &)
+ {
+ }
strerr = gmx_strerror(key);
sprintf(buf, "\n%s\nProgram %s, %s\n"
"Source code file: %s, line: %d\n\n"
"%s:\n%s\nFor more information and tips for troubleshooting, please check the GROMACS\n"
"website at http://www.gromacs.org/Documentation/Errors\n%s\n",
- llines, ShortProgram(), GromacsVersion(), file, line,
+ llines, programName, gmx_version(), file, line,
strerr, msg ? msg : errerrbuf, llines);
free(strerr);
#include "config.h"
#include <stdio.h>
+#include <stdlib.h>
#ifdef GMX_OPENMP
#include <omp.h>
#endif
-#include "gromacs/legacyheaders/copyrite.h"
-#include "gromacs/legacyheaders/md_logging.h"
-
#include "gromacs/utility/common.h"
#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/programcontext.h"
+#include "gromacs/utility/stringutil.h"
int gmx_omp_get_max_threads(void)
{
#endif
}
-/*!
- * Thread affinity set by the OpenMP library can conflict with the GROMACS
- * internal affinity setting.
- *
- * 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 honor it, disable the internal pinning, and warn the user.
- * When using Intel OpenMP, we will disable affinity if the user did not set it
- * anually through one of the aforementioned environment variables.
- *
- * Note that the Intel OpenMP affinity disabling iwll 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.
- */
-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)
{
- /* no need to worry if internal thread pinning is turned off */
- if (hw_opt->thread_affinity == threadaffOFF)
- {
- return;
- }
+ bool shouldSetAffinity = true;
-#ifndef GMX_OPENMP
- GMX_UNUSED_VALUE(fplog);
- GMX_UNUSED_VALUE(cr);
-#else
+ *message = NULL;
+#ifdef GMX_OPENMP
/* We assume that the affinity setting is available on all platforms
* gcc supports. Even if this is not the case (e.g. Mac OS) the user
* will only get a warning. */
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+ const char *programName;
+ try
+ {
+ programName = gmx::getProgramContext().displayName();
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
+
const char *const gomp_env = getenv("GOMP_CPU_AFFINITY");
const bool bGompCpuAffinitySet = (gomp_env != NULL);
/* turn off internal pinning if GOMP_CPU_AFFINITY is set & non-empty */
if (bGompCpuAffinitySet && *gomp_env != '\0')
{
- /* TODO: with -pin auto we should only warn when using all cores */
- md_print_warn(cr, fplog,
- "NOTE: GOMP_CPU_AFFINITY set, will turn off %s internal affinity\n"
- " setting as the two can conflict and cause performance degradation.\n"
- " To keep using the %s internal affinity setting, unset the\n"
- " GOMP_CPU_AFFINITY environment variable.",
- ShortProgram(), ShortProgram());
-
- hw_opt->thread_affinity = threadaffOFF;
+ try
+ {
+ std::string buf = gmx::formatString(
+ "NOTE: GOMP_CPU_AFFINITY set, will turn off %s internal affinity\n"
+ " setting as the two can conflict and cause performance degradation.\n"
+ " To keep using the %s internal affinity setting, unset the\n"
+ " GOMP_CPU_AFFINITY environment variable.",
+ programName, programName);
+ *message = gmx_strdup(buf.c_str());
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
+ shouldSetAffinity = false;
}
#endif /* __GNUC__ || __INTEL_COMPILER */
/* turn off internal pinning KMP_AFFINITY != "disabled" */
if (bKmpAffinitySet && (gmx_strncasecmp(kmp_env, "disabled", 8) != 0))
{
- /* TODO: with -pin auto we should only warn when using all cores */
- md_print_warn(cr, fplog,
- "NOTE: KMP_AFFINITY set, will turn off %s internal affinity\n"
- " setting as the two can conflict and cause performance degradation.\n"
- " To keep using the %s internal affinity setting, set the\n"
- " KMP_AFFINITY=disabled environment variable.",
- ShortProgram(), ShortProgram());
-
- hw_opt->thread_affinity = threadaffOFF;
+ try
+ {
+ std::string buf = gmx::formatString(
+ "NOTE: KMP_AFFINITY set, will turn off %s internal affinity\n"
+ " setting as the two can conflict and cause performance degradation.\n"
+ " To keep using the %s internal affinity setting, set the\n"
+ " KMP_AFFINITY=disabled environment variable.",
+ programName, programName);
+ *message = gmx_strdup(buf.c_str());
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
+ shouldSetAffinity = false;
}
#endif /* __INTEL_COMPILER */
#endif /* GMX_OPENMP */
+ return shouldSetAffinity;
}
#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
#include <windows.h>
#endif
-#include "types/commrec.h"
-#include "mdrun.h"
+#include "gromacs/legacyheaders/types/simple.h"
#ifdef __cplusplus
extern "C"
/*! \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.
#include "gromacs/mdlib/nbnxn_consts.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/utility/gmxmpi.h"
-#include "gromacs/utility/gmxomp.h"
#include "gromacs/swap/swapcoords.h"
#include "gromacs/essentialdynamics/edsam.h"
#include "gromacs/pulling/pull.h"
}
}
- /* Check for externally set OpenMP affinity and turn off internal
- * pinning if any is found. We need to do this check early to tell
- * thread-MPI whether it should do pinning when spawning threads.
- * TODO: the above no longer holds, we should move these checks down
- */
- gmx_omp_check_thread_affinity(fplog, cr, hw_opt);
-
/* Check and update the hardware options for internal consistency */
check_and_update_hw_opt_1(hw_opt, SIMMASTER(cr));
+ /* Early check for externally set process affinity. */
+ gmx_check_thread_affinity_set(fplog, cr,
+ hw_opt, hwinfo->nthreads_hw_avail, FALSE);
if (SIMMASTER(cr))
{
-#ifdef GMX_THREAD_MPI
- /* Early check for externally set process affinity.
- * With thread-MPI this is needed as pinning might get turned off,
- * which needs to be known before starting thread-MPI.
- * With thread-MPI hw_opt is processed here on the master rank
- * and passed to the other ranks later, so we only do this on master.
- */
- gmx_check_thread_affinity_set(fplog,
- NULL,
- hw_opt, hwinfo->nthreads_hw_avail, FALSE);
-#endif
#ifdef GMX_THREAD_MPI
if (cr->npmenodes > 0 && hw_opt->nthreads_tmpi <= 0)