76 votes

Comment vérifier si une CPU prend en charge le jeu d'instructions SSE3?

Le code suivant permet-il de vérifier si une CPU prend en charge le jeu d'instructions SSE3?

L'utilisation de la fonction IsProcessorFeaturePresent() fonctionne apparemment pas sous Windows XP (voir 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;      
}
 

111voto

Mysticial Points 180300

Voici un extrait de l'un de mes CPU répartiteurs.

Vous devez d'abord accéder à l'instruction CPUID:

#ifdef _WIN32

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

#else

//  GCC Inline Assembly
void cpuid(int CPUInfo[4],int InfoType){
    __asm__ __volatile__ (
        "cpuid":
        "=a" (CPUInfo[0]),
        "=b" (CPUInfo[1]),
        "=c" (CPUInfo[2]),
        "=d" (CPUInfo[3]) :
        "a" (InfoType), "c" (0)
    );
}

#endif

Ensuite, vous pouvez exécuter le code suivant:

//  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;

//  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

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_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;
}
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;
}

Noter que cette fonction ne détecte si le PROCESSEUR prend en charge les instructions. Pour exécuter eux, vous avez besoin de support du système d'exploitation.

Plus précisément, le système d'exploitation est nécessaire pour:

  • les instructions x64. (Vous avez besoin d'un OS 64 bits.)
  • Instructions d'utilisation de l' (AVX) 256-bit ymm registres. Voir Andy Lutomirski la réponse pour savoir comment détecter cette.
  • Instructions d'utilisation de l' (AVX512) de 512 bits zmm et le masque des registres.

58voto

Andy Lutomirski Points 443

Mysticial la réponse est un peu dangereux, il explique comment détecter le support du CPU, mais pas le support de l'OS. Vous avez besoin d'utiliser _xgetbv pour vérifier si le système d'exploitation a permis requis PROCESSEUR état étendu. Voir ici pour une autre source. Même gcc a fait la même erreur. La viande, le code est:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X