【问题标题】:How do I know if I can compile with FMA instruction sets?我如何知道我是否可以使用 FMA 指令集进行编译?
【发布时间】:2013-04-27 06:24:04
【问题描述】:

我看到了有关如何使用 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     

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

有谁知道如何找到它?谢谢。

【问题讨论】:

    标签: linux x86 intel processor fma


    【解决方案1】:

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

    FP_FAST_FMA 宏不是检测 FMA 指令集的可靠方法。如果std::fmax*y+z 快,则此宏在"math.h"/<cmath> 中定义,如果它是基于 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 Haswell 为 Intel 处理器引入了 FMA 和 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 ) 或使用-mfma 标志手动启用FMA 指令集。 ICC 使用 -xavx2 标志自动启用 FMA。 MSVC 使用 /arch:AVX2 /fp:fast /O2 选项启用 FMA。

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

    【讨论】:

    • 您在谈论编译时的检测,并且像您假设-march=native 一样谈论它。这是合理的,但应该提及。我指出这一点是因为您可以运行gcc -mtune=haswell -mavx2(没有-mfma),而不是运行gcc -march=haswellgcc -march=bdver2(Bulldozer version2 = Piledriver)。因此,这是一种可靠的方法来检测哪些目标选项仅在它们与真实硬件匹配时才启用,而不是在使用-m... 而不是-march= 手动选择的情况下。
    • @PeterCordes 你是对的,我更新了我的答案。
    • 看来 MSVC 不会生成带有 /arch:AVX2 的 fmas:godbolt.org/z/KvMjYjP5z
    • @user14717 你还需要/O2/fp:fast 标志:godbolt.org/z/TcWdP3GE4 我更新了我的答案。
    【解决方案2】:

    是的,如果你有它,它会出现在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
    

    在 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 macro

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 2016-02-17
      • 1970-01-01
      • 2013-06-11
      • 1970-01-01
      • 1970-01-01
      • 2021-01-28
      相关资源
      最近更新 更多