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