Avatar billede killer_r Nybegynder
13. august 2007 - 11:52 Der er 2 kommentarer og
1 løsning

MEX-fil crasher - C / Matlab problem

Hej Eksperter,

Jeg sidder og er ved at lave et program i MATLAB og jeg har en del af mit program der er seriøst langsomt i forhold til resten. Derfor vil jeg prøve at kode denne i en såkaldt MEX-fil (skrevet i C) for at få det til at køre hurtigere.

Jeg har aldrig før skrevet seriøst i C, men jeg har da fået strikket programmet sammen så det kan compiles. Problemet er bare at hvis jeg herefter kalder MEX-filen et par gange crasher den hele MATLAB. Hvor mange gange svinger lidt men alt fra mellem 5-20 kørsler, og så har vi balladen...

Er der ikke nogen derude der kan se om der er noget hukommelses-vrøvl i min kode eller andet der kan få MATLAB til at crashe.

På forhånd tak,
Killer_R

****************** KODEN KOMMER HER ******************

/*=================================================================
*
* model.c    .MEX file corresponding to model.m
*
* The calling syntax is:
*
*        [S] = model(t, gridp)
*
*=================================================================*/
#include <math.h>
#include "mex.h"

/* Input Arguments */
#define    T_IN    prhs[0]
#define    Y_IN    prhs[1]

/* Output Arguments */
#define    S_OUT    plhs[0]

#if !defined(MAX)
#define    MAX(A, B)    ((A) > (B) ? (A) : (B))
#endif

#if !defined(MIN)
#define    MIN(A, B)    ((A) < (B) ? (A) : (B))
#endif

static int len;

static int search(double t[], double value, int low, int high) {
    // Performs a binary search and finds the
    // indicies to that match. Searches indicies
    // between low and high.
    int p;
   
    if (value < t[0]) {
        return -1;
    }
    if (value > t[len]) {
        return len;
    }

    while (low <= high) {
        p = ceil((low+high)/2);
        if (t[p] > value) {
            high = p - 1;
        } else if (t[p] < value) {
            if (value < t[p+1]) {
                return p;
            }
            low = p + 1;
        } else {
            return p;
        }
    }
    return p;
}

static void model(double S[], double gridp[], double t[]) {
    // Extract information:
    double Width = gridp[0];
    double FirstTransit = gridp[1];
    double Period = gridp[2];
    double Depth = gridp[3];
    double tstart = t[0];
    double tend = t[len];
    int j, i, startv, slutv, w, nrtr;
   
    // Udregn tidspunkter for midt-transit:
    double M;
    int nmin = 0;
    int nr = floor((tend-tstart-FirstTransit)/Period) + 1;
    double Mend = tstart+FirstTransit+Period*nr;
    double Msta = tstart+FirstTransit;
    double t1end = Mend - Width/2;
    double t2sta = Msta + Width/2;
    // Dynamiske arrays:
    double *t1, *t2;
    int *k1, *k2;
   
    //mexPrintf("Width: %g \nFirstTransit: %g \nPeriod: %g \n",Width,FirstTransit,Period);
    //mexPrintf("tend: %g \ntstart: %g\n",tend,tstart);
   
    // Tjek af halve transits i starten og slutningen:
    if (Mend+Period > tend && t1end+Period < tend) { // Slutningen
        nr++;
    }
    if (Msta-Period < tstart && t2sta-Period > tstart) { // Starten
        nmin = -1;
    }
    // Giv t1 og t2 deres størrelser:
    nrtr = nr-nmin;
    //mexPrintf("nr: %d\nnmin: %d\nnrtr: %d\n",nr,nmin,nrtr);
    t1 = calloc(nrtr, sizeof(double));
    t2 = calloc(nrtr, sizeof(double));
    k1 = calloc(nrtr, sizeof(int));
    k2 = calloc(nrtr, sizeof(int));
   
    // Find tidspunkterne for transit:
    for (j=nmin; j<=nr; j++) {
        M = tstart+FirstTransit+Period*j;
        t1[j-nmin] = M - Width/2;
        t2[j-nmin] = M + Width/2;
    }
   
    // Den nye metode:
    startv = 0;
    slutv = len;
    for (j=1; j<=nrtr; j++) {
        if (j%2 == 0) {
            w = nrtr+1-j/2;
        } else {
            w = j-floor(j/2);
        }
        w = w-1; // vi er jo 0-baseret!

        k1[w] = search(t, t1[w], startv, slutv) + 1;
        k2[w] = search(t, t2[w], k1[w]+1, slutv);
       
        //mexPrintf("\nw: %d\n k1: %d\n k2: %d\n",w,k1[w],k2[w]);
       
        if (j%2 == 0) {
            slutv = k1[w]-1;
        } else {
            startv = k2[w]+1;
        }
    }
    free(t1);
    free(t2);
   
    // Lav model udfra index:
    for (j=0; j<nrtr; j++) {
        //mexPrintf("j: %d\n",j);
        for (i=k1[j]; i<=k2[j]; i++) {
            //mexPrintf("  i: %d\n",i);
            S[i] = -Depth;
        }
    }
   
    // Clean up:
    free(k1);
    free(k2);
    return;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[]) {
    double *S, *t, *gridp;
    mwSize m,n;
   
    /* Check for proper number of arguments */
    if (nrhs != 2) {
        mexErrMsgTxt("Two input arguments required.");
    } else if (nlhs > 1) {
        mexErrMsgTxt("Too many output arguments.");
    }
   
    /*  the dimensions of Y.  Y can be 4 X 1 or 1 X 4. */
    m = mxGetM(Y_IN);
    n = mxGetN(Y_IN);
    if (!mxIsDouble(Y_IN) || mxIsComplex(Y_IN) || (MAX(m,n) != 4) || (MIN(m,n) != 1)) {
        mexErrMsgTxt("model requires that gridp be a 4 x 1 vector.");
    }
   
    // Check T:
    m = mxGetM(T_IN);
    n = mxGetN(T_IN);
    if (!mxIsDouble(T_IN) || mxIsComplex(T_IN) || !(MAX(m,n) > 1) || (MIN(m,n) != 1)) {
        mexErrMsgTxt("model requires that t be a n x 1 vector.");
    }
    len = MAX(m,n)-1;
   
    /* Create a matrix for the return argument */
    S_OUT = mxCreateDoubleMatrix(MAX(m,n), 1, mxREAL);
   
    /* Assign pointers to the various parameters */
    S = mxGetPr(S_OUT);
    t = mxGetPr(T_IN);
    gridp = mxGetPr(Y_IN);
       
    /* Do the actual computations in a subroutine */
    model(S, gridp, t);
    return;
}
Avatar billede killer_r Nybegynder
14. august 2007 - 13:45 #1
Er der ingen der har en idé...? Please!
Avatar billede stefanfuglsang Juniormester
24. august 2007 - 10:00 #2
Er der ikke dette afsnit?
nmin=-1
nrtr = nr-nmin;

i t1[j-nmin]=... bliver j-nmin=nr-nmin=nrtr,
men t1 går fra 0 til nrtr-1
tilsvarende med t2

    if (Msta-Period < tstart && t2sta-Period > tstart) { // Starten
        nmin = -1;
    }
    // Giv t1 og t2 deres størrelser:
    nrtr = nr-nmin;
    //mexPrintf("nr: %d\nnmin: %d\nnrtr: %d\n",nr,nmin,nrtr);
    t1 = calloc(nrtr, sizeof(double));
    t2 = calloc(nrtr, sizeof(double));
    k1 = calloc(nrtr, sizeof(int));
    k2 = calloc(nrtr, sizeof(int));
   
    // Find tidspunkterne for transit:
    for (j=nmin; j<=nr; j++) {
        M = tstart+FirstTransit+Period*j;
        t1[j-nmin] = M - Width/2;
        t2[j-nmin] = M + Width/2;
    }
Avatar billede killer_r Nybegynder
24. august 2007 - 18:03 #3
Jeg fandt selv ud af det...
Det er når man laver disse MEX-filer i MATLAB, skal man bruge mxMalloc og mxFree istedet... Så virker det fint...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester