Archives pour la catégorie MATLAB

Erreur fatale du JRE au lancement de MATLAB (ntdll.dll)

A l’aide d’un MEX récalcitrant, j’ai fini par faire crasher MATLAB pour de bon.

Plus moyen de lancer MATLAB :?

J’ai trouvé des fichiers nommés « hs_err_pidXXXX.log » dans le dossier de démarrage de MATLAB.

Le début du contenu de ces fichiers est :

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000776508c5, pid=2328, tid=3600
#
# JRE version: 6.0_17-b04
# Java VM: Java HotSpot(TM) 64-Bit Server VM (14.3-b01 mixed mode windows-amd64 )
# Problematic frame:
# C  [ntdll.dll+0x508c5]
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

Le problème vient en fait d’un fichier corrompu dans le dossier des préférences MATLAB.

Sur Windows 7, le chemin vers ce dossier est le suivant :

C:\Users\<NOM D’UTILISATEUR>\AppData\Roaming\MathWorks\MATLAB\<VERSION DE MATLAB>

La solution est donc extrêmement simple et consiste à vider entièrement le contenu de ce dossier puis à démarrer MATLAB. De nouveaux fichiers de préférences seront automatiquement créés.

Si vous souhaitez conserver certains fichiers de préférences (les XML), déplacez simplement les fichiers dans un dossier temporaire puis démarrez MATLAB. Replacez un à un les fichiers à conserver dans le dossier des préférences en démarrant puis en fermant MATLAB à chaque fois.

Ouf !

Compilation de fichiers MEX sur Mac OS X

D’après le site de MathWorks, pour compiler des fichiers MEX avec les versions récentes de MATLAB sur Mac OS X, il suffit d’installer XCode (à partir du site Apple Developer ou à partir de l’Apple Store).

Par contre, une fois sous MATLAB, à la première compilation d’un fichier MEX, on reçoit un message d’erreur assez déroutant :

gcc-4.2: command not found

Après une brève recherche sur le support de MathWorks, on arrive sur la page suivante : Can I use Xcode 4.2 to 4.6 as my C or C++ compiler in MATLAB?

Il faut donc commencer par aller dans le menu « XCode > Preferences > Downloads » de XCode et installer, si ce n’est déjà fait, le composant « Command Line Tools» (la suite de compilateurs Gcc).

Après l’application du patch fourni par MathWorks, la compilation de fichiers MEX est opérationnelle 8-)

Note : il est sans doute possible de se passer de l’encombrant XCode en ne téléchargeant que le composant « Command Line Tools » directement sur le site Apple Developer – Open Source. Par contre, je ne sais pas si le patch fourni par MathWorks fonctionne sans XCode. Il y aura peut être des problèmes de chemins non disponibles. A tester…

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).