Basic support for transforming KeyValueTrees
[gromacs.git] / src / gromacs / simd / support.cpp
blobfb669014717b64f3e525c89742df3be626b78597
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2015,2016, 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_Avx512, "AVX_512" },
78 { SimdType::X86_Avx512Knl, "AVX_512_KNL" },
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_Avx512ER))
103 suggested = SimdType::X86_Avx512Knl;
105 else if (c.feature(CpuInfo::Feature::X86_Avx512F))
107 suggested = SimdType::X86_Avx512;
109 else if (c.feature(CpuInfo::Feature::X86_Avx2))
111 suggested = SimdType::X86_Avx2;
113 else if (c.feature(CpuInfo::Feature::X86_Avx))
115 suggested = SimdType::X86_Avx;
117 else if (c.feature(CpuInfo::Feature::X86_Sse4_1))
119 suggested = SimdType::X86_Sse4_1;
121 else if (c.feature(CpuInfo::Feature::X86_Sse2))
123 suggested = SimdType::X86_Sse2;
125 break;
126 case CpuInfo::Vendor::Amd:
127 if (c.feature(CpuInfo::Feature::X86_Avx2))
129 // When Amd starts supporting Avx2 we assume it will be 256 bits
130 suggested = SimdType::X86_Avx2;
132 else if (c.feature(CpuInfo::Feature::X86_Avx))
134 // Use 128-bit FMA SIMD if Fma4 flag is set, otherwise plain 256-bit AVX
135 if (c.feature(CpuInfo::Feature::X86_Fma4))
137 suggested = SimdType::X86_Avx128Fma;
139 else
141 suggested = SimdType::X86_Avx;
144 else if (c.feature(CpuInfo::Feature::X86_Sse4_1))
146 suggested = SimdType::X86_Sse4_1;
148 else if (c.feature(CpuInfo::Feature::X86_Sse2))
150 suggested = SimdType::X86_Sse2;
153 break;
154 case CpuInfo::Vendor::Arm:
155 if (c.feature(CpuInfo::Feature::Arm_NeonAsimd))
157 suggested = SimdType::Arm_NeonAsimd;
159 else if (c.feature(CpuInfo::Feature::Arm_Neon))
161 suggested = SimdType::Arm_Neon;
163 break;
164 case CpuInfo::Vendor::Ibm:
165 if (c.feature(CpuInfo::Feature::Ibm_Vsx))
167 suggested = SimdType::Ibm_Vsx;
169 else if (c.feature(CpuInfo::Feature::Ibm_Vsx))
171 suggested = SimdType::Ibm_Vsx;
173 else if (c.feature(CpuInfo::Feature::Ibm_Qpx))
175 suggested = SimdType::Ibm_Qpx;
177 break;
178 case CpuInfo::Vendor::Fujitsu:
179 if (c.feature(CpuInfo::Feature::Fujitsu_HpcAce))
181 suggested = SimdType::Fujitsu_HpcAce;
183 break;
184 default:
185 break;
188 return suggested;
191 SimdType
192 simdCompiled()
194 #if GMX_SIMD_X86_AVX_512_KNL
195 return SimdType::X86_Avx512Knl;
196 #elif GMX_SIMD_X86_AVX_512
197 return SimdType::X86_Avx512;
198 #elif GMX_SIMD_X86_MIC
199 return SimdType::X86_Mic;
200 #elif GMX_SIMD_X86_AVX2_256
201 return SimdType::X86_Avx2;
202 #elif GMX_SIMD_X86_AVX_256
203 return SimdType::X86_Avx;
204 #elif GMX_SIMD_X86_AVX_128_FMA
205 return SimdType::X86_Avx128Fma;
206 #elif GMX_SIMD_X86_SSE4_1
207 return SimdType::X86_Sse4_1;
208 #elif GMX_SIMD_X86_SSE2
209 return SimdType::X86_Sse2;
210 #elif GMX_SIMD_ARM_NEON
211 return SimdType::Arm_Neon;
212 #elif GMX_SIMD_ARM_NEON_ASIMD
213 return SimdType::Arm_NeonAsimd;
214 #elif GMX_SIMD_IBM_QPX
215 return SimdType::Ibm_Qpx;
216 #elif GMX_SIMD_IBM_VMX
217 return SimdType::Ibm_Vmx;
218 #elif GMX_SIMD_IBM_VSX
219 return SimdType::Ibm_Vsx;
220 #elif GMX_SIMD_SPARC64_HPC_ACE
221 return SimdType::Fujitsu_HpcAce;
222 #elif GMX_SIMD_REFERENCE
223 return SimdType::Reference;
224 #else
225 return SimdType::None;
226 #endif
229 bool
230 simdCheck(gmx::SimdType wanted,
231 FILE * log,
232 bool warnToStdErr)
234 SimdType compiled = simdCompiled();
236 // Normally it is close to catastrophic if the compiled SIMD type is larger than
237 // the supported one, but AVX128Fma is an exception: AMD CPUs will (strongly) prefer
238 // AVX128Fma, but they will work fine with AVX too. Thus, make an exception for this.
239 if (compiled > wanted && !(compiled == SimdType::X86_Avx && wanted == SimdType::X86_Avx128Fma))
241 fprintf(stderr, "Warning: SIMD instructions newer than hardware. Program will likely crash.\n"
242 "SIMD instructions most likely to fit this hardware: %s\n"
243 "SIMD instructions selected at GROMACS compile time: %s\n\n",
244 simdString(wanted).c_str(),
245 simdString(compiled).c_str());
247 else if (wanted != compiled)
249 // This warning will also occur if compiled is X86_Avx and wanted is X86_Avx128Fma
251 if (log != nullptr)
253 fprintf(log, "\nBinary not matching hardware - you might be losing performance.\n"
254 "SIMD instructions most likely to fit this hardware: %s\n"
255 "SIMD instructions selected at GROMACS compile time: %s\n\n",
256 simdString(wanted).c_str(),
257 simdString(compiled).c_str());
259 if (warnToStdErr)
261 fprintf(stderr, "Compiled SIMD instructions: %s, GROMACS could use %s on this machine, which is better.\n\n",
262 simdString(compiled).c_str(),
263 simdString(wanted).c_str());
266 return (wanted == compiled);
269 /*! \endcond */