Identification de processeur sous MATLAB (3/3)

Pour clôturer cette série de billets (lire les billets 1/3 et 2/3), je vais vous présenter rapidement une dernière méthode pour obtenir les caractéristiques du processeur (CPU) de votre machine.

Les méthodes présentées jusqu’à présent étaient soient incomplètes (voire incorrectes), soient différentes selon le système d’exploitation. Afin de corriger ces problèmes, nous allons utiliser une méthode très proche du CPU. Pour ce faire nous allons utiliser le langage assembleur et l’opcode CPUID.

Pour l’utiliser sous MATLAB, il est nécessaire de l’inclure dans un fichier MEX. Je vous propose donc deux versions écrites en C selon que vous utilisez les compilateurs Microsoft Visual C++ ou GNU gcc.

Voici le code pour gcc :

#include "mex.h"
#include <string.h>

void cpuid(int b[4], int a) {
   
    __asm( "cpuid"
            : "=a" (b[0]), "=b" (b[1]), "=c" (b[2]), "=d" (b[3])
            : "a"  (a));
           
}

void mexFunction( int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[] ) {
   
    int CPUInfo[4] = {-1};
    char CPUString[0x20];
    const mwSize dims[2] = {1,5};
   
    cpuid(CPUInfo, 0);
   
    memset(CPUString, 0, sizeof(CPUString));
    *((int*)CPUString) = CPUInfo[1];
    *((int*)(CPUString+4)) = CPUInfo[3];
    *((int*)(CPUString+8)) = CPUInfo[2];    
   
    plhs[0] = mxCreateCellArray(2, dims);
   
    mxSetCell(plhs[0], 4, mxCreateString(CPUString));
   
    cpuid(CPUInfo, 1);
   
    mxSetCell(plhs[0], 0, mxCreateDoubleScalar((double)((CPUInfo[0] >> 8) & 0xf)));
    mxSetCell(plhs[0], 1, mxCreateDoubleScalar((double)((CPUInfo[0] >> 16) & 0xf)));
    mxSetCell(plhs[0], 2, mxCreateDoubleScalar((double)((CPUInfo[0] >> 4) & 0xf)));
    mxSetCell(plhs[0], 3, mxCreateDoubleScalar((double)(CPUInfo[0] & 0xf)));
   
}

et le « même » pour Visual C++ :

#include "mex.h"
#include <string.h>
#include <intrin.h>

void mexFunction( int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[] ) {
   
    int CPUInfo[4] = {-1};
    char CPUString[0x20];
    const mwSize dims[2] = {1,5};
   
    __cpuid(CPUInfo, 0);
   
    memset(CPUString, 0, sizeof(CPUString));
    *((int*)CPUString) = CPUInfo[1];
    *((int*)(CPUString+4)) = CPUInfo[3];
    *((int*)(CPUString+8)) = CPUInfo[2];    
   
    plhs[0] = mxCreateCellArray(2, dims);
   
    mxSetCell(plhs[0], 4, mxCreateString(CPUString));
   
    __cpuid(CPUInfo, 1);
   
    mxSetCell(plhs[0], 0, mxCreateDoubleScalar((double)((CPUInfo[0] >> 8) & 0xf)));
    mxSetCell(plhs[0], 1, mxCreateDoubleScalar((double)((CPUInfo[0] >> 16) & 0xf)));
    mxSetCell(plhs[0], 2, mxCreateDoubleScalar((double)((CPUInfo[0] >> 4) & 0xf)));
    mxSetCell(plhs[0], 3, mxCreateDoubleScalar((double)(CPUInfo[0] & 0xf)));
   
}

A compiler comme ceci sous MATLAB :

mex getcpuinfosmx.c

Vous pourrez ensuite l’utiliser sous MATLAB comme ceci :

data = getcpuinfosmx;

fprintf('Family %d Extended Model %d Model %d Stepping %d, %s\n', ...
    data{1},data{2},data{3},data{4},strtrim(data{5}));

Ce qui renvoie bien les bonnes valeurs sur ma machine comme nous l’avons vu dans le billet précédent :

Family 6 Extended Model 2 Model 10 Stepping 7, GenuineIntel

On peut ensuite appliquer la méthodologie décrite dans les précédents billets pour retrouver le CPU dans les fiches constructeurs.

Dans le même esprit, voici un autre code pour récupérer la désignation commerciale du CPU.

Avec gcc :

#include "mex.h"
#include <string.h>

void cpuid(int b[4], int a) {
   
    __asm( "cpuid"
            : "=a" (b[0]), "=b" (b[1]), "=c" (b[2]), "=d" (b[3])
            : "a"  (a));
           
}

void mexFunction( int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[] ) {
   
    int CPUInfo[4] = {-1};
    char CPUBrandString[0x40];
   
    cpuid(CPUInfo, 0x80000000);
    memset(CPUBrandString, 0, sizeof(CPUBrandString));
   
    cpuid(CPUInfo, 0x80000002);
    memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
   
    cpuid(CPUInfo, 0x80000003);
    memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
   
    cpuid(CPUInfo, 0x80000004);
    memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
   
    plhs[0] = mxCreateString(CPUBrandString);
   
}

Sous Visual C++ :

#include "mex.h"
#include <string.h>
#include <intrin.h>

void mexFunction( int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[] ) {
   
    int CPUInfo[4] = {-1};
    char CPUBrandString[0x40];
   
    __cpuid(CPUInfo, 0x80000000);
    memset(CPUBrandString, 0, sizeof(CPUBrandString));
   
    __cpuid(CPUInfo, 0x80000002);
    memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
   
    __cpuid(CPUInfo, 0x80000003);
    memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
   
    __cpuid(CPUInfo, 0x80000004);
    memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
   
    plhs[0] = mxCreateString(CPUBrandString);
   
}

Une fois compilé, ce code me renvoi bien la bonne désignation du CPU de ma machine :

cpuname = getcpubrandstringmx

cpuname =

       Intel(R) Core(TM) i5-2430M CPU @ 2.40GHz

Voila, vous avez maintenant la possibilité d’identifier le CPU de votre machine sous MATLAB grâce à plusieurs méthodes.

Vous trouverez les fichiers MEX compilés (Windows, Linux et Mac) de getcpubrandstring ici.

Vous trouverez les fichiers sources C-MEX utilisés dans cet article ici.

Si vous voulez aller plus loin dans l’exploration des caractéristiques du CPU de votre machine, voici quelques liens utiles :

PS : les solutions proposées dans ce billet supposent que le CPU de votre machine connait les instructions CPUID (ce qui est le cas pour les processeurs Intel et AMD les plus couramment utilisés).

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>