Improve text writing in help output
[gromacs.git] / src / gromacs / simd / support.cpp
blob8ba1ec3334bee5959b51494d488eda91d52c5ca6
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2015, 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.
36 /*! \internal \file
38 * \brief Implements SIMD architecture support query routines
40 * \author Erik Lindahl <erik.lindahl@scilifelab.se>
42 * \ingroup module_simd
45 #include "gmxpre.h"
47 #include "support.h"
49 #include "config.h"
51 #include <cstdio>
52 #include <cstdlib>
54 #include <map>
55 #include <string>
57 #include "gromacs/hardware/cpuinfo.h"
59 namespace gmx
62 /*! \cond libapi */
64 const std::string &
65 simdString(SimdType s)
67 static const std::map<SimdType, std::string> name =
69 { SimdType::None, "None" },
70 { SimdType::Reference, "Reference" },
71 { SimdType::Generic, "Generic" },
72 { SimdType::X86_Sse2, "SSE2" },
73 { SimdType::X86_Sse4_1, "SSE4.1" },
74 { SimdType::X86_Avx128Fma, "AVX_128_FMA" },
75 { SimdType::X86_Avx, "AVX_256" },
76 { SimdType::X86_Avx2, "AVX2_256" },
77 { SimdType::X86_Avx512F, "AVX_512F" },
78 { SimdType::X86_Avx512ER, "AVX_512ER" },
79 { SimdType::X86_Mic, "X86_MIC" },
80 { SimdType::Arm_Neon, "ARM_NEON" },
81 { SimdType::Arm_NeonAsimd, "ARM_NEON_ASIMD" },
82 { SimdType::Ibm_Qpx, "IBM_QPX" },
83 { SimdType::Ibm_Vmx, "IBM_VMX" },
84 { SimdType::Ibm_Vsx, "IBM_VSX" },
85 { SimdType::Fujitsu_HpcAce, "Fujitsu HPC-ACE" }
88 return name.at(s);
91 SimdType
92 simdSuggested(const CpuInfo &c)
94 SimdType suggested = SimdType::None;
96 if (c.supportLevel() >= CpuInfo::SupportLevel::Features)
98 switch (c.vendor())
100 case CpuInfo::Vendor::Intel:
101 if (c.feature(CpuInfo::Feature::X86_Avx2))
103 suggested = SimdType::X86_Avx2;
105 else if (c.feature(CpuInfo::Feature::X86_Avx))
107 suggested = SimdType::X86_Avx;
109 else if (c.feature(CpuInfo::Feature::X86_Sse4_1))
111 suggested = SimdType::X86_Sse4_1;
113 else if (c.feature(CpuInfo::Feature::X86_Sse2))
115 suggested = SimdType::X86_Sse2;
117 break;
118 case CpuInfo::Vendor::Amd:
119 if (c.feature(CpuInfo::Feature::X86_Avx2))
121 // When Amd starts supporting Avx2 we assume it will be 256 bits
122 suggested = SimdType::X86_Avx2;
124 else if (c.feature(CpuInfo::Feature::X86_Avx))
126 // For vanilla Avx, we should use the 128-bit FMA flavor in Amd
127 suggested = SimdType::X86_Avx128Fma;
129 else if (c.feature(CpuInfo::Feature::X86_Sse4_1))
131 suggested = SimdType::X86_Sse4_1;
133 else if (c.feature(CpuInfo::Feature::X86_Sse2))
135 suggested = SimdType::X86_Sse2;
138 break;
139 case CpuInfo::Vendor::Arm:
140 if (c.feature(CpuInfo::Feature::Arm_NeonAsimd))
142 suggested = SimdType::Arm_NeonAsimd;
144 else if (c.feature(CpuInfo::Feature::Arm_Neon))
146 suggested = SimdType::Arm_Neon;
148 break;
149 case CpuInfo::Vendor::Ibm:
150 if (c.feature(CpuInfo::Feature::Ibm_Vsx))
152 suggested = SimdType::Ibm_Vsx;
154 else if (c.feature(CpuInfo::Feature::Ibm_Vsx))
156 suggested = SimdType::Ibm_Vsx;
158 else if (c.feature(CpuInfo::Feature::Ibm_Qpx))
160 suggested = SimdType::Ibm_Qpx;
162 break;
163 case CpuInfo::Vendor::Fujitsu:
164 if (c.feature(CpuInfo::Feature::Fujitsu_HpcAce))
166 suggested = SimdType::Fujitsu_HpcAce;
168 break;
169 default:
170 break;
173 return suggested;
176 SimdType
177 simdCompiled()
179 #if GMX_SIMD_X86_AVX_512ER
180 return SimdType::X86_Avx512ER;
181 #elif GMX_SIMD_X86_AVX_512F
182 return SimdType::X86_Avx512F;
183 #elif GMX_SIMD_X86_MIC
184 return SimdType::X86_Mic;
185 #elif GMX_SIMD_X86_AVX2_256
186 return SimdType::X86_Avx2;
187 #elif GMX_SIMD_X86_AVX_256
188 return SimdType::X86_Avx;
189 #elif GMX_SIMD_X86_AVX_128_FMA
190 return SimdType::X86_Avx128Fma;
191 #elif GMX_SIMD_X86_SSE4_1
192 return SimdType::X86_Sse4_1;
193 #elif GMX_SIMD_X86_SSE2
194 return SimdType::X86_Sse2;
195 #elif GMX_SIMD_ARM_NEON
196 return SimdType::Arm_Neon;
197 #elif GMX_SIMD_ARM_NEON_ASIMD
198 return SimdType::Arm_NeonAsimd;
199 #elif GMX_SIMD_IBM_QPX
200 return SimdType::Ibm_Qpx;
201 #elif GMX_SIMD_IBM_VMX
202 return SimdType::Ibm_Vmx;
203 #elif GMX_SIMD_IBM_VSX
204 return SimdType::Ibm_Vsx;
205 #elif GMX_SIMD_SPARC64_HPC_ACE
206 return SimdType::Fujitsu_HpcAce;
207 #elif GMX_SIMD_REFERENCE
208 return SimdType::Reference;
209 #else
210 return SimdType::None;
211 #endif
214 bool
215 simdCheck(gmx::SimdType wanted,
216 FILE * log,
217 bool warnToStdErr)
219 SimdType compiled = simdCompiled();
221 // Normally it is close to catastrophic if the compiled SIMD type is larger than
222 // the supported one, but AVX128Fma is an exception: AMD CPUs will (strongly) prefer
223 // AVX128Fma, but they will work fine with AVX too. Thus, make an exception for this.
224 if (compiled > wanted && !(compiled == SimdType::X86_Avx && wanted == SimdType::X86_Avx128Fma))
226 fprintf(stderr, "Warning: SIMD instructions newer than hardware. Program will likely crash.\n"
227 "SIMD instructions most likely to fit this hardware: %s\n"
228 "SIMD instructions selected at GROMACS compile time: %s\n\n",
229 simdString(wanted).c_str(),
230 simdString(compiled).c_str());
232 else
234 // This warning will also occur if compiled is X86_Avx and wanted is X86_Avx128Fma
236 if (log != nullptr)
238 fprintf(log, "\nBinary not matching hardware - you might be losing performance.\n"
239 "SIMD instructions most likely to fit this hardware: %s\n"
240 "SIMD instructions selected at GROMACS compile time: %s\n\n",
241 simdString(wanted).c_str(),
242 simdString(compiled).c_str());
244 if (warnToStdErr)
246 fprintf(stderr, "Compiled SIMD instructions: %s, GROMACS could use %s on this machine, which is better.\n\n",
247 simdString(compiled).c_str(),
248 simdString(wanted).c_str());
251 return (wanted == compiled);
254 /*! \endcond */