Почему этот MEXed C/magma code seg-fault, в то время как автономный C-код работает?

Следующий MEXed C-код просто обращается к магме, чтобы инвертировать матрицу. Автономный C-код (который также размещен) работает, но mex-код вылетает.

Я трижды проверил документацию, проверил, что другие функции магмы работают должным образом, и разместил на форуме Magma, и мне сказали, что мой код в порядке (это сообщение является перекрестным сообщением с форума Magma). Это означает, что проблема с mex. Я хотел бы знать, что приводит к тому, что mex-код вызывает ошибку и как заставить его работать так, как ожидалось.

Mexed код:

#include <mex.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stddef.h>
#include <magma_v2.h>
#include <cuda_runtime.h>

void mat2magma(magmaDoubleComplex* p, double* pr, double* pi,int numElements)
{
    int j=0;
    for(j=0;j<numElements;j++){
        p[j].x=pr[j];
        p[j].y=pi[j];
    }
}

void magma2mat(magmaDoubleComplex* p, double* pr, double* pi,int numElements)
{
    int j=0;
    for(j=0;j<numElements;j++){
        pr[j]= p[j].x;
        pi[j]= p[j].y;
    }
}

/*gateway function*/
void mexFunction( int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[]) {

    /*initialize magma*/
    magma_init();
    magma_queue_t queue = NULL;
    magma_device_t dev;
    magma_getdevice(&dev);
    magma_queue_create(dev,&queue );

    magma_int_t m,ldwork,info;
    magma_int_t *piv;
    magmaDoubleComplex *a,*da,*dwork;

    /* Matlab -> Host */
    m=mxGetM(prhs[0]);
    piv=(magma_int_t*) malloc(m*sizeof(magma_int_t));
    magma_zmalloc_cpu(&a,m*m);
    mat2magma(a,mxGetPr(prhs[0]),mxGetPi(prhs[0]),m*m);
    ldwork = m*magma_get_zgetri_nb(m);

    /* Host -> GPU */
    magma_zmalloc(&dwork,ldwork);
    magma_zmalloc(&da,m*m);
    magma_zsetmatrix(m,m,a,m,da,m,queue);

    /*LU and Inverse */
    magma_zgetrf_gpu(m,m,da,m,piv,&info);
    magma_zgetri_gpu(m,da,m,piv,dwork,ldwork,&info);

    /*GPU -> Host */
    magma_zgetmatrix(m,m,da,m,a,m,queue);

    /*Host -> Matlab*/
    plhs[0] = mxCreateDoubleMatrix(m,m,mxCOMPLEX);
    magma2mat(a,mxGetPr(plhs[0]),mxGetPi(plhs[0]),m*m);
    free(a);
    free(piv);
    magma_free(dwork);
    magma_free(da);
    magma_queue_destroy(queue);
    magma_finalize();
}

Я собрал это с mex CC=gcc LDFLAGS="-lmagma -lcudart -lcublas" magmaZinv.c потом из матлаба я побежал:

a=magic(3)+magic(3)*1i;
magmaZinv(a)

Автономный код C:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stddef.h>
#include <magma_v2.h>
#include <cuda_runtime.h>
#include <sys/time.h>
#include <time.h>

/*gateway function*/
int main() {

    /*initialize magma*/
    magma_init();
    magma_queue_t queue = NULL;
    magma_device_t dev;
    magma_getdevice(&dev);
    magma_queue_create(dev,&queue );

    int m,ldwork,info;
    int *piv;
    magmaDoubleComplex *a,*da,*dwork;

    /* allocate and initialize a = magic(3)+magic(3)*1i; */
    m=3;
    piv=(int*) malloc(m*sizeof(int));
    ldwork = m*magma_get_zgetri_nb(m);
    magma_zmalloc_cpu(&a,m*m);
    a[0].x=8;a[0].y=8;
    a[1].x=3;a[1].y=3;
    a[2].x=4;a[2].y=4;
    a[3].x=1;a[3].y=1;
    a[4].x=5;a[4].y=5;
    a[5].x=9;a[5].y=9;
    a[6].x=6;a[6].y=6;
    a[7].x=7;a[7].y=7;
    a[8].x=2;a[8].y=2;

    /* Host -> GPU */
    magma_zmalloc(&dwork,ldwork);
    magma_zmalloc(&da,m*m);
    magma_zsetmatrix(m,m,a,m,da,m,queue);

    /*LU and Inverse */
    magma_zgetrf_gpu(m,m,da,m,piv,&info);
    magma_zgetri_gpu(m,da,m,piv,dwork,ldwork,&info);

    /*GPU -> Host */
    magma_zgetmatrix(m,m,da,m,a,m,queue);

    /* display inv(a) */
    for (int i=0;i<(m*m);i++){
        printf("%f +%fi\n",a[i].x,a[i].y);
    }

    /* free memory */
    free(a);
    free(piv);
    magma_free(dwork);
    magma_free(da);
    magma_queue_destroy(queue);
    magma_finalize();

    return 0;
}

Я скомпилировал с: gcc -lmagma -lcudart Ccode.c -o Ccode.o

1 ответ

Мой системный администратор выяснил, почему автономный код C работает, а мексированный код C - нет. Я опубликую причину здесь, если она полезна для тех, кто сталкивается с такими же проблемами при использовании Magma из Matlab.

  1. Версия Matlab, которую я использовал, была 2014a. Поддерживаемый компилятор для этой версии - 4.7.x. Я использовал более высокую версию gcc для компиляции кода. У меня никогда не было проблем с использованием разных версий GCC с matlab, несмотря на предупреждение, которое он выдает, но для приведенного выше кода это имеет значение.

  2. Компилировать с MKL_ilp64 флаг при использовании Magma с Matlab, чтобы гарантировать, что magma_int_t имеет значение int64.

С этими двумя предложениями Магма может быть без проблем добавлена ​​в matlab.

Другие вопросы по тегам