Подтвердить что ты не робот

Как проверить, поддерживает ли процессор набор инструкций SSE3?

Является ли следующий код действительным для проверки того, поддерживает ли процессор набор инструкций SSE3?

Использование функции IsProcessorFeaturePresent(), по-видимому, не работает в Windows XP (см. http://msdn.microsoft.com/en-us/library/ms724482(v=vs.85).aspx).

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;      
}
4b9b3361

Ответ 1

Я создал GitHub-реестр, который обнаружит поддержку ЦП и ОС для всех основных расширений ISA x86: 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;
}

Обратите внимание, что это только определяет, поддерживает ли процессор инструкции. Чтобы запустить их, вам также потребуется поддержка операционной системы.

В частности, поддержка операционной системы требуется для:

  • x64. (Вам нужна 64-разрядная ОС.)
  • Инструкции, которые используют (AVX) 256-битные ymm регистры. См. ответ Энди Лутомирски о том, как это обнаружить.
  • Инструкции, в которых используются 512-битные регистры zmm и маска (AVX512). Обнаружение поддержки ОС для AVX512 такое же, как у AVX, но с использованием флага 0xe6 вместо 0x6.

Ответ 2

Мистический ответ немного опасен - в нем объясняется, как определить поддержку ЦП, но не поддерживать ОС. Вам нужно использовать _xgetbv, чтобы проверить, активировала ли ОС требуемое расширенное состояние 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;
}

Ответ 3

После недолгих поисков я также нашел решения от 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"))
    // ...

Если вы сложите это вместе с информацией выше, все будет хорошо.

Ответ 4

На Mac OS это работает:

sysctl -a | grep machdep.cpu.features

В моей машине это выводит это:

machdep.cpu.features: ФПУ УМЭ ДЕ ПСЭ ТСК МСР РАЙ МОК CX8 APIC сентябрь MTRR ПГЕ MCA CMOV РАТ PSE36 CLFSH DS ACPI МОГО FXSR SSE, SSE2, СС НТТ ТМ РВЕ SSE3 PCLMULQDQ DTES64 ПН DSCPL VMX EST ТМ2 SSSE3 ФМА CX16 Т PDCM SSE4.1 SSE4.2 x2APIC MOVBE POPCNT AES PCID XSAVE OSXSAVE SEGLIM64 TSCTMR AVX1.0 RDRAND F16C

Как вы можете видеть из инструкций, написанных жирным шрифтом, SSE3 и куча других инструкций SIMD поддерживаются.

Ответ 5

Чтобы добавить в Abhiroop ответ: В linux вы можете запустить эту команду оболочки, чтобы узнать функции, поддерживаемые вашим процессором.

cat/proc/cpuinfo | grep flags | uniq

На моей машине это печатает

флаги: FPU VME-де-псевдоэфедрин TSC MSR пае MCE CX8 APIC SEP MTRR PGE MCA CMOV погладить pse36 clflush MMX fxsr ссе sse2 ХТ системный вызов пх pdpe1gb rdtscp лм constant_tsc rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu ПНИ PCLMULQDQ SSSE3 FMA CX16 PCID sse4_1 sse4_2 x2APIC movbe POPCNT tsc_deadline_timer АЕС xsave avx f16c гипервизор rdrand lahf_lm abm 3dnowprefetch invpcid_single retpoline kaiser fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx xsaveopt