【问题标题】:Intrinsics for CPUID like informations?CPUID 的内在信息之类的信息?
【发布时间】:2013-07-19 11:11:34
【问题描述】:

考虑到我正在使用 C++ 进行编码,如果可能的话,我想使用类似 Intrinsics 的解决方案来阅读有关硬件的有用信息,我的担忧/考虑是:

  • 我不太了解汇编,仅获取此类信息将是一笔可观的投资(虽然它看起来像 CPU,但它只是关于翻转值和读取寄存器。)
  • 至少有 2 种流行的 asm 语法(Intel 和 AT&T),所以它是零散的
  • 奇怪的是,如今 Intrinsics 比 asm 代码更受欢迎和受支持
  • 目前我所关注的并非所有编译器都支持内联 asm,MSVC 64 位就是其中之一;恐怕我在深入挖掘我必须使用的不同编译器的功能集时会发现其他类似的缺陷。
  • 考虑到我认为押注 Intrinsics 对我来说更有效率,它也应该比任何 asm 代码更容易。

我要回答的最后一个问题是:如何用内在函数做类似的事情?因为除了 CPUID 操作码之外,我没有找到任何其他信息来获取此类信息。

【问题讨论】:

  • Clang 有一个集成的汇编器,它对 Intel 风格的汇编的支持有时参差不齐。无法在 Intel 风格下生成简单的negate (neg)

标签: c++ intrinsics cpuid


【解决方案1】:

经过一番挖掘 I have found 后,一个有用的内置函数是 gcc 特定的。

唯一的问题是这种功能真的很有限(基本上你只有2个功能,1个用于CPU“名称”,1个用于寄存器组)

一个例子是

#include <stdio.h>

int main()
{
    if (__builtin_cpu_supports("mmx")) {
        printf("\nI got MMX !\n");
    } else
        printf("\nWhat ? MMX ? What is that ?\n");
    return (0);
}

显然这个内置函数也可以在 mingw-w64 下工作。

【讨论】:

  • 来自问题:“并非所有编译器......都支持内联asm,MSVC 64位是一个”。提供的代码当然不适用于 Microsoft 编译器。在您拥有 GCC 和 MS 解决方案之前,您应该避免接受您的答案。
【解决方案2】:

Gcc 包含一个 cpuid 接口:

http://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/i386/cpuid.h

这些似乎没有很好的记录,但可以在此处找到示例用法:

http://gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=gcc/config/i386/driver-i386.c

请注意,当 ecx 的初始值很重要时(例如 avx/avx2 检测),您必须使用 __cpuid_count() 而不是 __cpuid()

正如 user2485710 所指出的,gcc 可以为您完成所有 cpu 特征检测工作。从 gcc 4.8.1 开始,__builtin_cpu_supports() 支持的完整功能列表为:cmov、mmx、popcnt、sse、sse2、sse3、ssse3、sse4.1、sse4.2、avx 和 avx2。

【讨论】:

    【解决方案3】:

    诸如此类的内在函数通常也是特定于编译器的。

    MS VC++ 有一个__cpuid(和一个__cpuidex)来生成一个CPUID 操作码。

    至少据我所知,gcc/g++ 并没有提供与之等效的功能。内联汇编似乎是唯一可用的选项。

    【讨论】:

    • gcc 提供了一个 cpuid.h 标头,该标头提供了一个 __cpuid 宏(请注意,与 MSVC 的定义不同)以及一个 __get_cpuid 函数。
    【解决方案4】:

    对于 x86/x64,英特尔提供了一个名为 _may_i_use_cpu_feature 的内部函数。您可以在Intel Intrinsics Guide 页面的常规支持 类别下找到它。以下是英特尔文档的翻录。

    GCC 应该在内部函数方面遵循 Intel,因此它应该在 GCC 下可用。我不清楚微软是否提供了它,因为它们提供了大多数(但不是全部)英特尔内在函数。

    我对 ARM 没有任何了解。据我所知,ARM下没有__builtin_cpu_supports("neon")__builtin_cpu_supports("crc32")__builtin_cpu_supports("aes")__builtin_cpu_supports("pmull")__builtin_cpu_supports("sha")等。对于 ARM,您必须执行 CPU feature probing


    Synopsis
    
    int _may_i_use_cpu_feature (unsigned __int64 a)
    
    #include "immintrin.h"
    
    Description
    
    Dynamically query the processor to determine if the processor-specific feature(s) specified
    in a are available, and return true or false (1 or 0) if the set of features is
    available. Multiple features may be OR'd together. This intrinsic does not check the
    processor vendor. See the valid feature flags below:
    
    Operation
    
        _FEATURE_GENERIC_IA32
        _FEATURE_FPU
        _FEATURE_CMOV
        _FEATURE_MMX
        _FEATURE_FXSAVE
        _FEATURE_SSE
        _FEATURE_SSE2
        _FEATURE_SSE3
        _FEATURE_SSSE3
        _FEATURE_SSE4_1
        _FEATURE_SSE4_2
        _FEATURE_MOVBE
        _FEATURE_POPCNT
        _FEATURE_PCLMULQDQ
        _FEATURE_AES
        _FEATURE_F16C
        _FEATURE_AVX
        _FEATURE_RDRND
        _FEATURE_FMA
        _FEATURE_BMI
        _FEATURE_LZCNT
        _FEATURE_HLE
        _FEATURE_RTM
        _FEATURE_AVX2
        _FEATURE_KNCNI
        _FEATURE_AVX512F
        _FEATURE_ADX
        _FEATURE_RDSEED
        _FEATURE_AVX512ER
        _FEATURE_AVX512PF
        _FEATURE_AVX512CD
        _FEATURE_SHA
        _FEATURE_MPX
    

    【讨论】:

    【解决方案5】:

    对于曾孙,这是使用GCC获取CPU供应商名称的方法,在Win7 x64上测试

        #include <cpuid.h>
        ...
        int eax, ebx, ecx, edx;
        char vendor[13];
        __cpuid(0, eax, ebx, ecx, edx);
        memcpy(vendor, &ebx, 4);
        memcpy(vendor + 4, &edx, 4);
        memcpy(vendor + 8, &ecx, 4);
        vendor[12] = '\0';
        printf("CPU: %s\n", vendor);
    

    【讨论】:

    • 我希望我的曾祖父和你一样酷。谢谢。
    猜你喜欢
    • 2021-03-20
    • 2011-10-03
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多