use*_*490 6 linux x86 processor intel fma
我已经看到有关如何使用FMA指令集的问题,但在我开始使用它们之前,我首先想知道我是否可以(我的处理器是否支持它们).我找到一篇帖子说我需要查看(在Linux上工作)的输出:
more /proc/cpuinfo
Run Code Online (Sandbox Code Playgroud)
找出来.我明白了:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Xeon(R) CPU X3470 @ 2.93GHz
stepping : 5
cpu MHz : 2933.235
size : 8192 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni
dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm ida dts tpr_shadow vnmi flexpriority ept vpid
bogomips : 5866.47
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
Run Code Online (Sandbox Code Playgroud)
看起来最有趣的是标志部分,但我不知道如果处理器支持这些指令,如何从该列表中找出.
有人知道如何找到它吗?谢谢.
这是一个古老的问题,但仍然是一个相关的问题.
我假设你想在编译时用C/C++检测它.
FP_FAST_FMA宏不是检测FMA指令集的可靠方法.这个宏在"math.h"/ <cmath>if中定义std::fma得更快x*y+z,如果它是基于FMA指令集的内部函数,则可以实现.否则它将使用非常慢的非内在函数.现在在2016年,GCC的默认glibc/libstdc ++定义了这个宏,但大多数其他标准库实现都没有(包括LLVM libc ++,ICC和MSVC).它并不意味着std::fma如果可能的话它们不会作为内在实现,它们只是忘了定义这个宏.
可靠的FMA检测
要在编译时可靠地检测FMA(或任何指令集),您需要使用指令集特定的宏.这些宏由编译器基于所选择的目标体系结构和/或指令集来定义.
有一个__FMA__支持FMA/FMA3 的宏,以及__FMA4__支持AMD FMA4的宏.GCC,clang和ICC确实对它们进行了定义.
不幸的是,MSVC没有定义除__AVX__和之外的任何指令集特定的宏__AVX2__.
交叉编译器FMA检测
对于Intel处理器,FMA是由Intel Haswell推出的AVX2 .
对于AMD处理器来说,事情有点混乱.FMA4由AMD Bulldozer推出AVX和XOP .AMD Piledriver推出了FMA3(Intel FMA等效产品).您可以在编译时通过FMA(__FMA__宏)和BMI(__BMI__宏)指令集来区分Piledriver与其前身Bulldozer .不幸的是,MSVC没有定义.
然而,与英特尔处理器一样,如果存在AVX2,所有AMD处理器都支持FMA/FMA3.
如果您希望交叉编译器检测目标体系结构是否支持FMA/FMA3,则必须检测__AVX2__宏,因为如果启用了AVX2,它将由所有主要编译器(包括MSVC)定义:
#if !defined(__FMA__) && defined(__AVX2__)
#define __FMA__ 1
#endif
Run Code Online (Sandbox Code Playgroud)
遗憾的是,没有可靠的方法来仅使用__AVX__和__AVX2__宏检测AMD FMA4 .
笔记
只有在编译器启用FMA指令时,才能在程序中使用FMA指令.在GCC和clang中,您需要设置正确的目标体系结构(如-march=haswell)或手动启用带-mfma标志的FMA指令集.ICC自动启用FMA-xavx2标志.MSVC使用该/arch:AVX2选项自动启用FMA.
AMD宣布将在未来放弃对FMA4的支持.
是的,如果有它,它将显示在flags零件下面。在Intel Haswell机器上,我得到
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm ida arat xsaveopt pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm
Run Code Online (Sandbox Code Playgroud)
在AMD打桩机上,我得到了
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc extd_apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 popcnt aes xsave avx f16c lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 tce nodeid_msr tbm topoext perfctr_core perfctr_nb arat cpb hw_pstate npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold bmi1
Run Code Online (Sandbox Code Playgroud)
(请注意,它包括一个fma4标志以及标准fma标志)。
因此,在Linux上检查的一种简单方法是查看以下代码的返回代码:
grep fma < /proc/cpuinfo
Run Code Online (Sandbox Code Playgroud)
OS X没有/proc/cpuinfo,但是您可以执行以下操作:
sysctl -n hw.optional.fma
Run Code Online (Sandbox Code Playgroud)
它将打印0(无fma)或1(有fma)。
如果您使用的是C / C ++,则还可以使用FP_FAST_FMA宏。