7da093b53461450e7a8bf3ff9d177b57085ae704
[alexxy/gromacs.git] / src / gromacs / utility / gmxomp.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, 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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \internal \file
36  * \brief
37  * Implements functions from gmxomp.h.
38  *
39  * \ingroup module_utility
40  */
41 #include "gromacs/utility/gmxomp.h"
42
43 #include "config.h"
44
45 #include <stdio.h>
46 #include <stdlib.h>
47
48 #ifdef GMX_OPENMP
49 #include <omp.h>
50 #endif
51
52 #include "gromacs/utility/common.h"
53 #include "gromacs/utility/cstringutil.h"
54 #include "gromacs/utility/exceptions.h"
55 #include "gromacs/utility/fatalerror.h"
56 #include "gromacs/utility/programcontext.h"
57 #include "gromacs/utility/stringutil.h"
58
59 int gmx_omp_get_max_threads(void)
60 {
61 #ifdef GMX_OPENMP
62     return omp_get_max_threads();
63 #else
64     return 1;
65 #endif
66 }
67
68 int gmx_omp_get_num_procs(void)
69 {
70 #ifdef GMX_OPENMP
71     return omp_get_num_procs();
72 #else
73     return 1;
74 #endif
75 }
76
77 int gmx_omp_get_thread_num(void)
78 {
79 #ifdef GMX_OPENMP
80     return omp_get_thread_num();
81 #else
82     return 0;
83 #endif
84 }
85
86 void gmx_omp_set_num_threads(int num_threads)
87 {
88 #ifdef GMX_OPENMP
89     omp_set_num_threads(num_threads);
90 #else
91     GMX_UNUSED_VALUE(num_threads);
92 #endif
93 }
94
95 gmx_bool gmx_omp_check_thread_affinity(char **message)
96 {
97     bool shouldSetAffinity = true;
98
99     *message = NULL;
100 #ifdef GMX_OPENMP
101     /* We assume that the affinity setting is available on all platforms
102      * gcc supports. Even if this is not the case (e.g. Mac OS) the user
103      * will only get a warning. */
104 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
105     const char *programName;
106     try
107     {
108         programName = gmx::getProgramContext().displayName();
109     }
110     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
111
112     const char *const gomp_env            = getenv("GOMP_CPU_AFFINITY");
113     const bool        bGompCpuAffinitySet = (gomp_env != NULL);
114
115     /* turn off internal pinning if GOMP_CPU_AFFINITY is set & non-empty */
116     if (bGompCpuAffinitySet && *gomp_env != '\0')
117     {
118         try
119         {
120             std::string buf = gmx::formatString(
121                         "NOTE: GOMP_CPU_AFFINITY set, will turn off %s internal affinity\n"
122                         "      setting as the two can conflict and cause performance degradation.\n"
123                         "      To keep using the %s internal affinity setting, unset the\n"
124                         "      GOMP_CPU_AFFINITY environment variable.",
125                         programName, programName);
126             *message = gmx_strdup(buf.c_str());
127         }
128         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
129         shouldSetAffinity = false;
130     }
131 #endif /* __GNUC__ || __INTEL_COMPILER */
132
133 #if defined(__INTEL_COMPILER)
134     const char *const kmp_env         = getenv("KMP_AFFINITY");
135     const bool        bKmpAffinitySet = (kmp_env != NULL);
136
137     /* disable Intel OpenMP affinity if neither KMP_AFFINITY nor
138      * GOMP_CPU_AFFINITY is set (Intel uses the GNU env. var as well) */
139     if (!bKmpAffinitySet && !bGompCpuAffinitySet)
140     {
141         int retval;
142
143 #ifdef _MSC_VER
144         /* Windows not POSIX */
145         retval = _putenv_s("KMP_AFFINITY", "disabled");
146 #else
147         /* POSIX */
148         retval = setenv("KMP_AFFINITY", "disabled", 0);
149 #endif  /* _MSC_VER */
150
151         if (debug)
152         {
153             fprintf(debug, "Disabling Intel OpenMP affinity by setting the KMP_AFFINITY=disabled env. var.\n");
154         }
155
156         if (retval != 0)
157         {
158             gmx_warning("Disabling Intel OpenMp affinity setting failed!");
159         }
160     }
161
162     /* turn off internal pinning KMP_AFFINITY != "disabled" */
163     if (bKmpAffinitySet && (gmx_strncasecmp(kmp_env, "disabled", 8) != 0))
164     {
165         try
166         {
167             std::string buf = gmx::formatString(
168                         "NOTE: KMP_AFFINITY set, will turn off %s internal affinity\n"
169                         "      setting as the two can conflict and cause performance degradation.\n"
170                         "      To keep using the %s internal affinity setting, set the\n"
171                         "      KMP_AFFINITY=disabled environment variable.",
172                         programName, programName);
173             *message = gmx_strdup(buf.c_str());
174         }
175         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
176         shouldSetAffinity = false;
177     }
178 #endif /* __INTEL_COMPILER */
179
180 #endif /* GMX_OPENMP */
181     return shouldSetAffinity;
182 }