8

我已经看到有关如何使用 FMA 指令集的问题,但在我开始使用它们之前,我首先想知道我是否可以(我的处理器是否支持它们)。我发现一个帖子说我需要查看(在 Linux 上工作)的输出:

more /proc/cpuinfo

找出答案。我明白了:

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     

最有趣的是标志部分,但我不确定如何从该列表中找出处理器是否支持这些指令。

有人知道如何找出来吗?谢谢你。

4

2 回答 2

13

我假设您想在编译时在 C/C++ 中检测它。

FP_FAST_FMA宏不是检测 FMA 指令集的可靠方法。此宏定义在"math.h"/ <cmath>if std::fmais faster thanx*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__and之外的任何指令集特定宏__AVX2__

交叉编译器 FMA 检测

对于 Intel 处理器,FMA 由Intel Haswell与 AVX2 一起引入。

对于 AMD 处理器,事情有点混乱。FMA4 由AMD Bulldozer与 AVX 和 XOP 一起引入。FMA3(英特尔 FMA 等效)由AMD Piledriver引入。__FMA__通过 FMA(宏)和 BMI(__BMI__宏)指令集的存在,您可以在编译时将 Piledriver 与其前身 Bulldozer 区分开来。不幸的是,MSVC 两者都没有定义。

不过,与 Intel 处理器一样,如果存在 AVX2,则所有 AMD 处理器都支持 FMA/FMA3。

如果要交叉编译器检测目标架构是否支持 FMA/FMA3,则必须检测__AVX2__宏,因为如果启用了 AVX2,它由所有主要编译器(包括 MSVC)定义:

#if !defined(__FMA__) && defined(__AVX2__)
    #define __FMA__ 1
#endif

不幸的是,没有可靠的方法来仅使用__AVX____AVX2__宏来检测 AMD FMA4。

笔记

只有当编译器启用 FMA 指令时,它才能在您的程序中实际可用。在 GCC 和 clang 中,您需要设置正确的目标架构(如标志-march=haswell的 FMA 指令集ICC 使用标志-mfma自动启用 FMA-xavx2MSVC 通过/arch:AVX2 /fp:fast /O2选项启用 FMA。

AMD 宣布未来将放弃对 FMA4 的支持。

于 2016-11-23T13:32:51.807 回答
6

是的,如果你有它,它会出现在flags部件下面。在英特尔 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

在 AMD Piledriver 上,我得到

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

(请注意,它包括一个fma4标志,以及标准fma标志)。

因此,在 Linux 上检查的一种简单方法是查看以下返回码:

grep fma < /proc/cpuinfo

OS X 没有/proc/cpuinfo,但您可以改为:

sysctl -n hw.optional.fma

这将打印 0(无 fma)或 1(有 fma)。

如果你使用 C/C++,你也可以使用FP_FAST_FMA.

于 2014-12-09T09:18:23.697 回答