70

次のコードは、CPUがSSE3命令セットをサポートしているかどうかを確認するために有効ですか?

このIsProcessorFeaturePresent()機能の使用は、WindowsXPでは明らかに機能しません。

bool CheckSSE3()
{
    int CPUInfo[4] = {-1};

    //-- Get number of valid info ids
    __cpuid(CPUInfo, 0);
    int nIds = CPUInfo[0];

    //-- Get info for id "1"
    if (nIds >= 1)
    {
        __cpuid(CPUInfo, 1);
        bool bSSE3NewInstructions = (CPUInfo[2] & 0x1) || false;
        return bSSE3NewInstructions;     
    }

    return false;      
}
4

6 に答える 6

103

すべての主要なx86ISA拡張機能のCPUとOSのサポートを検出するGitHubリプロを作成しました:https ://github.com/Mysticial/FeatureDetector

これが短いバージョンです:


まず、CPUID命令にアクセスする必要があります。

#ifdef _WIN32

//  Windows
#define cpuid(info, x)    __cpuidex(info, x, 0)

#else

//  GCC Intrinsics
#include <cpuid.h>
void cpuid(int info[4], int InfoType){
    __cpuid_count(InfoType, 0, info[0], info[1], info[2], info[3]);
}

#endif

次に、次のコードを実行できます。

//  Misc.
bool HW_MMX;
bool HW_x64;
bool HW_ABM;      // Advanced Bit Manipulation
bool HW_RDRAND;
bool HW_BMI1;
bool HW_BMI2;
bool HW_ADX;
bool HW_PREFETCHWT1;

//  SIMD: 128-bit
bool HW_SSE;
bool HW_SSE2;
bool HW_SSE3;
bool HW_SSSE3;
bool HW_SSE41;
bool HW_SSE42;
bool HW_SSE4a;
bool HW_AES;
bool HW_SHA;

//  SIMD: 256-bit
bool HW_AVX;
bool HW_XOP;
bool HW_FMA3;
bool HW_FMA4;
bool HW_AVX2;

//  SIMD: 512-bit
bool HW_AVX512F;    //  AVX512 Foundation
bool HW_AVX512CD;   //  AVX512 Conflict Detection
bool HW_AVX512PF;   //  AVX512 Prefetch
bool HW_AVX512ER;   //  AVX512 Exponential + Reciprocal
bool HW_AVX512VL;   //  AVX512 Vector Length Extensions
bool HW_AVX512BW;   //  AVX512 Byte + Word
bool HW_AVX512DQ;   //  AVX512 Doubleword + Quadword
bool HW_AVX512IFMA; //  AVX512 Integer 52-bit Fused Multiply-Add
bool HW_AVX512VBMI; //  AVX512 Vector Byte Manipulation Instructions

int info[4];
cpuid(info, 0);
int nIds = info[0];

cpuid(info, 0x80000000);
unsigned nExIds = info[0];

//  Detect Features
if (nIds >= 0x00000001){
    cpuid(info,0x00000001);
    HW_MMX    = (info[3] & ((int)1 << 23)) != 0;
    HW_SSE    = (info[3] & ((int)1 << 25)) != 0;
    HW_SSE2   = (info[3] & ((int)1 << 26)) != 0;
    HW_SSE3   = (info[2] & ((int)1 <<  0)) != 0;

    HW_SSSE3  = (info[2] & ((int)1 <<  9)) != 0;
    HW_SSE41  = (info[2] & ((int)1 << 19)) != 0;
    HW_SSE42  = (info[2] & ((int)1 << 20)) != 0;
    HW_AES    = (info[2] & ((int)1 << 25)) != 0;

    HW_AVX    = (info[2] & ((int)1 << 28)) != 0;
    HW_FMA3   = (info[2] & ((int)1 << 12)) != 0;

    HW_RDRAND = (info[2] & ((int)1 << 30)) != 0;
}
if (nIds >= 0x00000007){
    cpuid(info,0x00000007);
    HW_AVX2   = (info[1] & ((int)1 <<  5)) != 0;

    HW_BMI1        = (info[1] & ((int)1 <<  3)) != 0;
    HW_BMI2        = (info[1] & ((int)1 <<  8)) != 0;
    HW_ADX         = (info[1] & ((int)1 << 19)) != 0;
    HW_SHA         = (info[1] & ((int)1 << 29)) != 0;
    HW_PREFETCHWT1 = (info[2] & ((int)1 <<  0)) != 0;

    HW_AVX512F     = (info[1] & ((int)1 << 16)) != 0;
    HW_AVX512CD    = (info[1] & ((int)1 << 28)) != 0;
    HW_AVX512PF    = (info[1] & ((int)1 << 26)) != 0;
    HW_AVX512ER    = (info[1] & ((int)1 << 27)) != 0;
    HW_AVX512VL    = (info[1] & ((int)1 << 31)) != 0;
    HW_AVX512BW    = (info[1] & ((int)1 << 30)) != 0;
    HW_AVX512DQ    = (info[1] & ((int)1 << 17)) != 0;
    HW_AVX512IFMA  = (info[1] & ((int)1 << 21)) != 0;
    HW_AVX512VBMI  = (info[2] & ((int)1 <<  1)) != 0;
}
if (nExIds >= 0x80000001){
    cpuid(info,0x80000001);
    HW_x64   = (info[3] & ((int)1 << 29)) != 0;
    HW_ABM   = (info[2] & ((int)1 <<  5)) != 0;
    HW_SSE4a = (info[2] & ((int)1 <<  6)) != 0;
    HW_FMA4  = (info[2] & ((int)1 << 16)) != 0;
    HW_XOP   = (info[2] & ((int)1 << 11)) != 0;
}

これは、CPUが命令をサポートしているかどうかのみを検出することに注意してください。実際に実行するには、オペレーティングシステムのサポートも必要です。

具体的には、オペレーティングシステムのサポートが必要です。

  • x64命令。(64ビットOSが必要です。)
  • (AVX)256ビットymmレジスタを使用する命令。これを検出する方法については、AndyLutomirskiの回答を参照してください。
  • (AVX512)512ビットzmmおよびマスクレジスタを使用する命令。AVX512のOSサポートの検出はAVXの場合と同じですが、の0xe6代わりにフラグを使用し0x6ます。
于 2011-09-21T05:33:32.993 に答える
56

Mysticialの答えは少し危険です。CPUサポートを検出する方法を説明していますが、OSサポートを検出する方法は説明していません。_xgetbvを使用して、OSが必要なCPU拡張状態を有効にしているかどうかを確認する必要があります。別の情報源 については、こちらをご覧ください。gccでさえ同じ間違いを犯しました。 コードの要点は次のとおりです。

bool avxSupported = false;

int cpuInfo[4];
__cpuid(cpuInfo, 1);

bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;

if (osUsesXSAVE_XRSTORE && cpuAVXSuport)
{
    unsigned long long xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
    avxSupported = (xcrFeatureMask & 0x6) == 0x6;
}
于 2014-03-20T01:22:27.933 に答える
11

かなりグーグルした後、私はIntelのソリューションも見つけました。

リンク:https ://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family

    void cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd) {
#if defined(_MSC_VER)
            __cpuidex((int*)abcd, eax, ecx);
#else
            uint32_t ebx, edx;
# if defined( __i386__ ) && defined ( __PIC__ )
            /* in case of PIC under 32-bit EBX cannot be clobbered */
            __asm__("movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx),
# else
            __asm__("cpuid" : "+b" (ebx),
# endif
            "+a" (eax), "+c" (ecx), "=d" (edx));
            abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx;
#endif
    }

    int check_xcr0_ymm()
    {
        uint32_t xcr0;
#if defined(_MSC_VER)
        xcr0 = (uint32_t)_xgetbv(0);  /* min VS2010 SP1 compiler is required */
#else
        __asm__("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx");
#endif
        return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */
    }

また、GCCには、使用できるいくつかの特別な組み込み関数があることに注意してください(https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/X86-Built-in-Functions.htmlを参照)。

    if (__builtin_cpu_supports("avx2"))
    // ...

これを上記の情報と組み合わせると、すべてうまくいきます。

于 2015-02-10T20:53:24.673 に答える
8

Abhiroopの回答に追加するには:Linuxでは、このシェルコマンドを実行して、CPUでサポートされている機能を確認できます。

cat /proc/cpuinfo | grep flags | uniq

私のマシンでは、これは

フラグ:FPU VMEデPSE TSC MSR PAE MCE CX8 APIC 9月MTRR PGEのMCA CMOVパットPSE36 CLFLUSH MMX fxsr SSE、SSE2 HTシステムコールNX pdpe1gb rdtscp LM CONSTANT_TSC rep_good nopl xtopology NONSTOP_TSC aperfmperf eagerfpu PNI PCLMULQDQ SSSE3 FMA cx16 PCID sse4_1 sse4_2 x2apicにMOVBE POPCNT tsc_deadline_timer AES xsave avxf16crdrandハイパーバイザーlahf_lmabm3dnowprefetch invpcid_single retpoline kaiser fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx xsaveopt

于 2018-03-26T19:51:18.157 に答える
6

Mac OSでは、これは機能します。

sysctl -a | grep machdep.cpu.features

私のマシンでは、これを出力します。

machdep.cpu.features:FPU VME DE PSE TSC MSR PAE MCE CX8 APIC SEP MTRR PGE MCA CMOV PAT PSE36 CLFSH DS ACPI MMX FXSR SSE SSE2 SS HTT TM PBE SSE3 PCLMULQDQ DTES64 MON DSCPL VMX EST TM2 SSSE3 FMA CX16 SSE4.2 x2APIC MOVBE POPCNT AES PCID XSAVE OSXSAVE SEGLIM64 TSCTMR AVX1.0 RDRAND F16C

太字で書かれた命令でわかるように、SSE3と他のSIMD命令の束がサポートされています。

于 2018-03-03T01:01:21.283 に答える
3

Linuxまたはwsl2のAlternativleyは、 util-linuxリポジトリlscpuからのコマンドがその役割を果たします。

例えば:

lscpu | grep sse3
于 2021-03-05T01:59:15.610 に答える