如何以编程方式检查 CPU 上是不是启用了 fused mul add (FMA) 指令?

Posted

技术标签:

【中文标题】如何以编程方式检查 CPU 上是不是启用了 fused mul add (FMA) 指令?【英文标题】:How to programmatically check if fused mul add (FMA) instruction are enabled on the CPU?如何以编程方式检查 CPU 上是否启用了 fused mul add (FMA) 指令? 【发布时间】:2019-11-19 10:47:24 【问题描述】:

我想使用 FMA 内部指令 _mm256_fmadd_pd(a, b, c),但我的代码必须在启用或不启用 FMA 的不同计算机上运行。我不能使用编译时标志。所以我希望能够写出这样的东西:

__m256d a, b, c, x;
bool FMA_Enabled = CheckFMA();

if (FMA_Enabled)

  d = _mm256_fmadd_pd(a, b, c);

else

  x = _mm256_mul_pd(a, b);
  d = _mm256_add_pd(x, c);

我找不到编写函数 CheckFMA() 的方法。有没有办法做到这一点?

我的操作系统是 Windows 10 64 位。

编辑:分支实际上将在函数之外。所以我不会因为每次都检查 FMA 支持而损失性能。

【问题讨论】:

你是说增加的乘法性能优于分支(否则没有必要)?你测量过这个吗? @lisyarus 不,这没有错。每个 CPU 都有用于特征检测的 API,因此不必输入无效指令。 见***.com/q/6121792/2747962 查看__cpuid Microsoft intrinic 并检查AVX2FMA 函数。 @DanielsaysreinstateMonica:_mm256_fmadd_pd 只需要 AVX 和 FMA3 功能位,而不需要 AVX2。您不想不必要地排除 AMD Piledriver/Steamroller。从技术上讲,您需要检查操作系统是否支持 AVX(以及 CPU),但 Windows 程序可能能够假定非古代 Windows。真的只需要检查 FMA3 功能位;它暗示了 AVX,因为这就是它的编码方式。 (与 AMD 放弃的 FMA4 功能相反) 【参考方案1】:

我使用 __cpuid 通过修改 microsoft 代码来编写我的函数。非常感谢大家的帮助。

#include <intrin.h>
#include <vector>
#include <bitset>
#include <array>

bool CheckFMA()

    std::array<int, 4> cpui;
    std::bitset<32> ECX;
    int nIds;
    bool fma;

    __cpuid(cpui.data(), 0);
    nIds = cpui[0];

    if (nIds < 1)
    
        return false;
    

    __cpuidex(cpui.data(), 1, 0);
    ECX = cpui[2];

    return ECX[12];

【讨论】:

您不需要在循环中调用cpuid 来枚举所有可能的输出。您只需要在if(nIds_ &gt;= 1) 中使用__cpuidex(cpui.data(), 1, 0) 即可获得您读过的一页。这对性能来说并不是一个巨大的灾难,例如Ice Lake only has 0x1B "basic" / 低编号 CPUID 留待枚举。所以它不会让启动需要额外的毫秒。 @PeterCordes。是的,谢谢。我将在我的帖子中更正这一点。 不要把笨重的版本留在答案中,只显示好的版本。或者至少把它放在第一位。编辑以创建您应该首先发布的答案;如果有人想看,编辑历史就在那里。 顺便说一句,理论上(如果您的代码可能在古老的操作系统下运行),您需要检查操作系统对 AVX 的支持是否已启用。 Which versions of Windows support/require which CPU multimedia extensions?。操作系统必须在 CPU 中设置一个位以使它们不会出错。 (这避免了在不知道新架构状态的操作系统上的上下文切换上损坏的 AVX 上半部分的故障模式。)【参考方案2】:

哪个操作系统?运行 linux,您可以检查 /proc/cpuinfo,例如fma 标志

使用 Windows 看看https://docs.microsoft.com/en-us/sysinternals/downloads/coreinfo 使用了GetLogicalProcessorInformation 函数

【讨论】:

我忘了指定操作系统:它是 windows 10 64 位。 直接使用cpuid 不会比其中任何一个更容易(而且更快)吗? 我认为 cpuid 是正确的方法。非常感谢

以上是关于如何以编程方式检查 CPU 上是不是启用了 fused mul add (FMA) 指令?的主要内容,如果未能解决你的问题,请参考以下文章

如何在android studio上以编程方式检查自动启动权限是启用还是禁用

如何以编程方式检查系统上是不是安装了 SQL Server Management Studio?

如何以编程方式在WooCommerce产品中启用评论和评分?

如何在android中以编程方式启用位置访问?

如何以编程方式检测是不是在 Windows 桌面应用程序中启用/禁用了 javascript? (网络浏览器控件)

如何通过使用 C、C++ 在 Linux 上指定其名称以编程方式检查特定守护程序是不是正在运行?