【问题标题】:Why does this MEXed C/magma code seg-fault while the stand alone C code works?为什么这个 MEXed C/magma 代码段错误,而独立 C 代码工作?
【发布时间】:2019-01-21 20:57:58
【问题描述】:

以下 MEXed C 代码仅调用 magma 以反转矩阵。独立的 C 代码(也已发布)有效,但 mex 代码崩溃。

我已经三遍检查了文档,验证了其他 magma 功能是否按预期工作,并且 posted on the Magma forum and was told my code is fine(这篇文章是来自 Magma 论坛的交叉帖子)。这意味着问题出在mex上。我想知道是什么导致 mex 代码出现段错误以及如何让它按预期运行。

混合代码:

#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 编译它然后从 matlab 中运行:

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

【问题讨论】:

  • 段错误在哪里?
  • 调用 magma_zgetrf_gpu 时发生 seg-fault。如果 magma_zgetrf_gpu 和 magma_zgetri_gpu 调用都被注释,则 MEXed 代码运行良好,只需将未更改的输入矩阵返回到 LHS。
  • 尝试在这些调用之前使用mexPrintf 打印一些值。最可能的情况是某些错误的类型已传递给这些输入变量之一。打印其中的 1 个元素,并查看哪个打印给出了段错误(或打印垃圾)。
  • 我实际上在每个阶段都尝试过。每一个论点都是正确的。事实上,如果我不调用这两个函数,矩阵从 prhs -> 主机内存从 matlab 转换为交错 -> gpu 内存 -> 主机内存从交错转换为 matlab -> plhs。成功地。我真的很难过!我需要这个代码!
  • 必须有区别,否则该函数在 C 和 mex 版本中会做同样的事情。一旦暴力调试方法是创建一个函数,它将在magma_zgetrf_gpu 调用之前将所有变量保存到一个文本文件中。对两个版本使用完全相同的函数,并保存所有输入变量。然后试着看看有什么问题。但是,如果一切都一样,则预期会出现相同的行为,最终,计算机是确定性的。

标签: c matlab gpu mex magma


【解决方案1】:

我的系统管理员已经弄清楚了为什么独立的 C 代码可以工作,而混合的 C 代码却不能。我将在此处发布原因,因为它对在 Matlab 中使用 Magma 时遇到相同问题的任何人都有帮助。

  1. 我使用的 Matlab 版本是 2014a。此版本的 supported compiler 是 4.7.x。我正在使用更高版本的 gcc 来编译代码。尽管它给出了警告,但我从来没有遇到过在 matlab 中使用不同版本的 GCC 的问题,但对于上面的代码,它确实很重要。

  2. Compile with the MKL_ilp64 flag when using Magma with Matlab 确保 magma_int_t 是 int64。

有了这两个建议,Magma 可以毫无问题地混合到 matlab 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-28
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多