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.
38 * \brief Implements SIMD architecture support query routines
40 * \author Erik Lindahl <erik.lindahl@scilifelab.se>
42 * \ingroup module_simd
57 #include "gromacs/hardware/cpuinfo.h"
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" }
92 simdSuggested(const CpuInfo
&c
)
94 SimdType suggested
= SimdType::None
;
96 if (c
.supportLevel() >= CpuInfo::SupportLevel::Features
)
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
;
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
;
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
;
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
;
163 case CpuInfo::Vendor::Fujitsu
:
164 if (c
.feature(CpuInfo::Feature::Fujitsu_HpcAce
))
166 suggested
= SimdType::Fujitsu_HpcAce
;
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
;
210 return SimdType::None
;
215 simdCheck(gmx::SimdType wanted
,
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());
234 // This warning will also occur if compiled is X86_Avx and wanted is X86_Avx128Fma
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());
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
);