Turn on -Wunused-parameter where applicable
[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, 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 #ifdef GMX_OPENMP
46 #include <omp.h>
47 #endif
48
49 #include <stdio.h>
50
51 #include "md_logging.h"
52 #include "gmx_fatal.h"
53 #include "statutil.h"
54 #include "string2.h"
55
56 #include "common.h"
57
58 int gmx_omp_get_max_threads(void)
59 {
60 #ifdef GMX_OPENMP
61     return omp_get_max_threads();
62 #else
63     return 1;
64 #endif
65 }
66
67 int gmx_omp_get_num_procs(void)
68 {
69 #ifdef GMX_OPENMP
70     return omp_get_num_procs();
71 #else
72     return 1;
73 #endif
74 }
75
76 int gmx_omp_get_thread_num(void)
77 {
78 #ifdef GMX_OPENMP
79     return omp_get_thread_num();
80 #else
81     return 0;
82 #endif
83 }
84
85 void gmx_omp_set_num_threads(int num_threads)
86 {
87 #ifdef GMX_OPENMP
88     omp_set_num_threads(num_threads);
89 #else
90     GMX_UNUSED_VALUE(num_threads);
91 #endif
92 }
93
94 /*!
95  * Thread affinity set by the OpenMP library can conflict with the GROMACS
96  * internal affinity setting.
97  *
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.
101  *
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.
107  *
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
111  * pragmas.
112  */
113 void gmx_omp_check_thread_affinity(FILE            *fplog,
114                                    const t_commrec *cr,
115                                    gmx_hw_opt_t    *hw_opt)
116 {
117     /* no need to worry if internal thread pinning is turned off */
118     if (hw_opt->thread_affinity == threadaffOFF)
119     {
120         return;
121     }
122
123 #ifndef GMX_OPENMP
124     GMX_UNUSED_VALUE(fplog);
125     GMX_UNUSED_VALUE(cr);
126 #else
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);
133
134     /* turn off internal pinning if GOMP_CPU_AFFINITY is set & non-empty */
135     if (bGompCpuAffinitySet && *gomp_env != '\0')
136     {
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());
144
145         hw_opt->thread_affinity = threadaffOFF;
146     }
147 #endif /* __GNUC__ || __INTEL_COMPILER */
148
149 #if defined(__INTEL_COMPILER)
150     const char *const kmp_env         = getenv("KMP_AFFINITY");
151     const bool        bKmpAffinitySet = (kmp_env != NULL);
152
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)
156     {
157         int retval;
158
159 #ifdef _MSC_VER
160         /* Windows not POSIX */
161         retval = _putenv_s("KMP_AFFINITY", "disabled");
162 #else
163         /* POSIX */
164         retval = setenv("KMP_AFFINITY", "disabled", 0);
165 #endif  /* _MSC_VER */
166
167         if (debug)
168         {
169             fprintf(debug, "Disabling Intel OpenMP affinity by setting the KMP_AFFINITY=disabled env. var.\n");
170         }
171
172         if (retval != 0)
173         {
174             gmx_warning("Disabling Intel OpenMp affinity setting failed!");
175         }
176     }
177
178     /* turn off internal pinning KMP_AFFINITY != "disabled" */
179     if (bKmpAffinitySet && (gmx_strncasecmp(kmp_env, "disabled", 8) != 0))
180     {
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());
188
189         hw_opt->thread_affinity = threadaffOFF;
190     }
191 #endif /* __INTEL_COMPILER */
192
193 #endif /* GMX_OPENMP */
194 }