2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Implements functions from gmxomp.h.
39 * \ingroup module_utility
41 #include "gromacs/utility/gmxomp.h"
52 #include "md_logging.h"
53 #include "gmx_fatal.h"
58 int gmx_omp_get_max_threads(void)
61 return omp_get_max_threads();
67 int gmx_omp_get_num_procs(void)
70 return omp_get_num_procs();
76 int gmx_omp_get_thread_num(void)
79 return omp_get_thread_num();
85 void gmx_omp_set_num_threads(int num_threads)
88 omp_set_num_threads(num_threads);
90 GMX_UNUSED_VALUE(num_threads);
95 * Thread affinity set by the OpenMP library can conflict with the GROMACS
96 * internal affinity setting.
98 * While GNU OpenMP does not set affinity by default, the Intel OpenMP library
99 * does. This conflicts with the internal affinity (especially thread-MPI)
100 * setting, results in incorrectly locked threads, and causes dreadful performance.
102 * The KMP_AFFINITY environment variable is used by Intel, GOMP_CPU_AFFINITY
103 * by the GNU compilers (Intel also honors it well). If any of the variables
104 * is set, we honor it, disable the internal pinning, and warn the user.
105 * When using Intel OpenMP, we will disable affinity if the user did not set it
106 * anually through one of the aforementioned environment variables.
108 * Note that the Intel OpenMP affinity disabling iwll only take effect if this
109 * function is called before the OpenMP library gets initialized which happens
110 * when the first call is made into a compilation unit that contains OpenMP
113 void gmx_omp_check_thread_affinity(FILE *fplog,
115 gmx_hw_opt_t *hw_opt)
117 /* no need to worry if internal thread pinning is turned off */
118 if (hw_opt->thread_affinity == threadaffOFF)
124 GMX_UNUSED_VALUE(fplog);
125 GMX_UNUSED_VALUE(cr);
127 /* We assume that the affinity setting is available on all platforms
128 * gcc supports. Even if this is not the case (e.g. Mac OS) the user
129 * will only get a warning. */
130 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
131 const char *const gomp_env = getenv("GOMP_CPU_AFFINITY");
132 const bool bGompCpuAffinitySet = (gomp_env != NULL);
134 /* turn off internal pinning if GOMP_CPU_AFFINITY is set & non-empty */
135 if (bGompCpuAffinitySet && *gomp_env != '\0')
137 /* TODO: with -pin auto we should only warn when using all cores */
138 md_print_warn(cr, fplog,
139 "NOTE: GOMP_CPU_AFFINITY set, will turn off %s internal affinity\n"
140 " setting as the two can conflict and cause performance degradation.\n"
141 " To keep using the %s internal affinity setting, unset the\n"
142 " GOMP_CPU_AFFINITY environment variable.",
143 ShortProgram(), ShortProgram());
145 hw_opt->thread_affinity = threadaffOFF;
147 #endif /* __GNUC__ || __INTEL_COMPILER */
149 #if defined(__INTEL_COMPILER)
150 const char *const kmp_env = getenv("KMP_AFFINITY");
151 const bool bKmpAffinitySet = (kmp_env != NULL);
153 /* disable Intel OpenMP affinity if neither KMP_AFFINITY nor
154 * GOMP_CPU_AFFINITY is set (Intel uses the GNU env. var as well) */
155 if (!bKmpAffinitySet && !bGompCpuAffinitySet)
160 /* Windows not POSIX */
161 retval = _putenv_s("KMP_AFFINITY", "disabled");
164 retval = setenv("KMP_AFFINITY", "disabled", 0);
165 #endif /* _MSC_VER */
169 fprintf(debug, "Disabling Intel OpenMP affinity by setting the KMP_AFFINITY=disabled env. var.\n");
174 gmx_warning("Disabling Intel OpenMp affinity setting failed!");
178 /* turn off internal pinning KMP_AFFINITY != "disabled" */
179 if (bKmpAffinitySet && (gmx_strncasecmp(kmp_env, "disabled", 8) != 0))
181 /* TODO: with -pin auto we should only warn when using all cores */
182 md_print_warn(cr, fplog,
183 "NOTE: KMP_AFFINITY set, will turn off %s internal affinity\n"
184 " setting as the two can conflict and cause performance degradation.\n"
185 " To keep using the %s internal affinity setting, set the\n"
186 " KMP_AFFINITY=disabled environment variable.",
187 ShortProgram(), ShortProgram());
189 hw_opt->thread_affinity = threadaffOFF;
191 #endif /* __INTEL_COMPILER */
193 #endif /* GMX_OPENMP */