使用mex将Matlab中的大矩阵传递给C:Matlab崩溃

Gar*_*ngh 0 c c++ matlab matrix mex

我编写了一个mex代码,它从matlab代码向C代码发送标量和矩阵.它适用于较小的矩阵.但是,当我尝试传递大的稀疏矩阵(大小~8448 x 3264)时,matlab崩溃并出现以下错误:

我收到以下错误:Matlab遇到内部问题,需要关闭.

                  *Detailed error report*


------------------------------------------------------------------------
         Segmentation violation detected at Mon Feb  9 13:21:48 2015
  ------------------------------------------------------------------------

  Configuration:
    Crash Decoding     : Disabled
    Current Visual     : None
    Default Encoding   : UTF-8
    GNU C Library      : 2.19 stable
    MATLAB Architecture: glnxa64
    MATLAB Root        : /usr/local/MATLAB/R2014b
    MATLAB Version     : 8.4.0.150421 (R2014b)
    Operating System   : Linux 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64
    Processor ID       : x86 Family 6 Model 44 Stepping 2, GenuineIntel
    Software OpenGL    : 1
    Virtual Machine    : Java 1.7.0_11-b21 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
    Window System      : No active display

  Fault Count: 1


  Abnormal termination:
  Segmentation violation

  Register State (from fault):
    RAX = 00007f011f000000  RBX = 0000000000000001
    RCX = 0000000000260fe0  RDX = 00007f0162197000
    RSP = 00007f024fffb4f0  RBP = 00007f024fffb4f0
    RSI = 00007f011ed9f020  RDI = 00007f0161f36020

     R8 = 00007f011ed9f010   R9 = 0000000000000000
    R10 = 0000000000000022  R11 = 0000000048000001
    R12 = 00007f024fffbaf0  R13 = 00007f01c63b57f0
    R14 = 00007f024fffbb00  R15 = 00007f024fffbb00

    RIP = 00007f01618d491e  EFL = 0000000000010206

     CS = 0033   FS = 0000   GS = 0000

  Stack Trace (from fault):
  [  0] 0x00007f01618d491e /home/dkumar/Mex_Codes_DKU/Matlab_Calling_C/Test_2/mexcallingmatlab.mexa64+00002334
  [  1] 0x00007f01618d4a8e /home/dkumar/Mex_Codes_DKU/Matlab_Calling_C/Test_2/mexcallingmatlab.mexa64+00002702 mexFunction+00000325
  [  2] 0x00007f025ef7ac0a     /usr/local/MATLAB/R2014b/bin/glnxa64/libmex.so+00150538 mexRunMexFile+00000090
  [  3] 0x00007f025ef775c4     /usr/local/MATLAB/R2014b/bin/glnxa64/libmex.so+00136644
  [  4] 0x00007f025ef78414     /usr/local/MATLAB/R2014b/bin/glnxa64/libmex.so+00140308
  [  5] 0x00007f025e2af329 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_dispatcher.so+00791337 _ZN8Mfh_file11dispatch_fhEiPP11mxArray_tagiS2_+00000697
  [  6] 0x00007f025d189b70 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+04053872
  [  7] 0x00007f025d139e02 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03726850
  [  8] 0x00007f025d13c022 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03735586
  [  9] 0x00007f025d141f87 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03760007
  [ 10] 0x00007f025d13d6ff /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03741439
  [ 11] 0x00007f025d13e334 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03744564
  [ 12] 0x00007f025d1b352e /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+04224302
  [ 13] 0x00007f025e2af329 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_dispatcher.so+00791337 _ZN8Mfh_file11dispatch_fhEiPP11mxArray_tagiS2_+00000697
  [ 14] 0x00007f025d189b70 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+04053872
  [ 15] 0x00007f025d10a293 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03531411
  [ 16] 0x00007f025d13b0de /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03731678
  [ 17] 0x00007f025d141f87 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03760007
  [ 18] 0x00007f025d13d6ff /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03741439
  [ 19] 0x00007f025d13e334 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03744564
  [ 20] 0x00007f025d1b352e /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+04224302
  [ 21] 0x00007f025e2af4af /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_dispatcher.so+00791727 _ZN8Mfh_file11dispatch_fhEiPP11mxArray_tagiS2_+00001087
  [ 22] 0x00007f025d171ff5 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03956725
  [ 23] 0x00007f025d133699 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03700377
  [ 24] 0x00007f025d12fa87 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03684999
  [ 25] 0x00007f025d130143 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwm_interpreter.so+03686723
  [ 26] 0x00007f025f1bb9dc /usr/local/MATLAB/R2014b/bin/glnxa64/libmwbridge.so+00223708
  [ 27] 0x00007f025f1bc649 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwbridge.so+00226889 _Z8mnParserv+00000729
  [ 28] 0x00007f02698c6b7f   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00772991 _ZN11mcrInstance30mnParser_on_interpreter_threadEv+00000031
  [ 29] 0x00007f02698a7083   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00643203
  [ 30] 0x00007f02698a8d69   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00650601 _ZN5boost6detail11task_objectIvNS_3_bi6bind_tIvPFvRKNS_8functionIFvvEEEENS2_5list1INS2_5valueIS6_EEEEEEE6do_runEv+00000025
  [ 31] 0x00007f02698a9737   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00653111 _ZN5boost6detail9task_baseIvE3runEv+00000071
  [ 32] 0x00007f02698a9797   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00653207
  [ 33] 0x00007f02698a4bca   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00633802
  [ 34] 0x00007f025c4eaa46   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwuix.so+00330310
  [ 35] 0x00007f025c4d2ad2   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwuix.so+00232146
  [ 36] 0x00007f026a06700f /usr/local/MATLAB/R2014b/bin/glnxa64/libmwservices.so+02523151
  [ 37] 0x00007f026a06717c /usr/local/MATLAB/R2014b/bin/glnxa64/libmwservices.so+02523516
  [ 38] 0x00007f026a06307f /usr/local/MATLAB/R2014b/bin/glnxa64/libmwservices.so+02506879
  [ 39] 0x00007f026a0684b5 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwservices.so+02528437
  [ 40] 0x00007f026a0688e7 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwservices.so+02529511
  [ 41] 0x00007f026a068fc0 /usr/local/MATLAB/R2014b/bin/glnxa64/libmwservices.so+02531264 _Z25svWS_ProcessPendingEventsiib+00000080
  [ 42] 0x00007f02698a5248   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00635464
  [ 43] 0x00007f02698a5564   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00636260
  [ 44] 0x00007f0269891cdd   /usr/local/MATLAB/R2014b/bin/glnxa64/libmwmcr.so+00556253
  [ 45] 0x00007f026877b182              /lib/x86_64-linux-gnu/libpthread.so.0+00033154
  [ 46] 0x00007f02684a7fbd                    /lib/x86_64-linux-gnu/libc.so.6+01028029 clone+00000109


  This error was detected while a MEX-file was running. If the MEX-file
  is not an official MathWorks function, please examine its source code
  for errors. Please consult the External Interfaces Guide for information
  on debugging MEX-files.
Run Code Online (Sandbox Code Playgroud)

这是我的matlab代码:

% Create system matrix (size 8448 x 3264)
smA_System = ConstructSystemMatrix();

    x = 9;
    y = ones(3);

    % This works fine
    z = mexcallingmatlab(x, y);

    % This gives error
    z = mexcallingmatlab(x, smA_System);
Run Code Online (Sandbox Code Playgroud)

这是我的mex代码

  #include "mex.h"

  void xtimesy(double x, double *y, double *z, int m, int n)
  {
    int i,j,count = 0;

    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
            *(z+count) = x * *(y+count);
            count++;
        }
    }
  }


  void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  {
    double *y, *z;
    double x;
    int status,mrows,ncols;


    if (nrhs != 2) 
        mexErrMsgTxt("Two inputs required.");
    if (nlhs != 1) 
        mexErrMsgTxt("One output required.");

    /* Check to make sure the first input argument is a scalar. */
    if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
        mxGetN(prhs[0])*mxGetM(prhs[0]) != 1) {
        mexErrMsgTxt("Input x must be a scalar.");
    }

    /* Get the scalar input x. */
    x = mxGetScalar(prhs[0]);

    /* Create a pointer to the input matrix y. */
    y = mxGetPr(prhs[1]);

    /* Get the dimensions of the matrix input y. */
    mrows = mxGetM(prhs[1]);
    ncols = mxGetN(prhs[1]);

    /* Set the output pointer to the output matrix. */
    plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL);

    /* Create a C pointer to a copy of the output matrix. */
    z = mxGetPr(plhs[0]); 

    /* Call the C subroutine. */
    xtimesy(x, y, z, mrows, ncols);    // Passing x as a scalar and y,z as pointer; possibly implicit converion of y,z to their pointers

  }
Run Code Online (Sandbox Code Playgroud)

更新:谢谢,Shai指出我的错误.如果你能回答另一个问题,我将不胜感激.传递稀疏矩阵的最佳方法是什么? 1)通过将指针传递给矩阵,就像我在我的mex文件中所做的那样2)通过将指针传递给非零元素,如下所示:

[rows cols values] = find(smA_System);
[nrows ncols] = size(smA_System);
Run Code Online (Sandbox Code Playgroud)

然后,将指针传递给rows,cols,values.

Sha*_*hai 6

正如您在问题中指出的那样,您的代码仅适用于读取full矩阵作为第二个参数.什么prhs[1]是稀疏矩阵时,你不能再使用它作为完整矩阵访问它*(y+count):它是SPARSE,它不占用n内存中的entires,但更少.
要在mex中访问稀疏矩阵的元素,您应该使用mxGetIr和mxGetJc.这里最好地解释了 Matlab存储稀疏矩阵的方式.
此外,输入矩阵是稀疏的,而输出矩阵已满 - 这在尝试分配输出矩阵时可能会导致内存不足错误.然而,你可能不是plhs[0]从mxCreateDoubleMatrix(mrows,ncols, mxREAL);它返回的检查NULL.

更新:

最佳做法是将稀疏矩阵原样传递给您的mex代码.
在您的mex功能中,您应该:

  1. 按预期验证输入确实是稀疏的.见mxIsSparse.
  2. 获得使用三个相关的指针(四为复杂基质)mxGetIr,mxGetJc和mxGetPr.
  3. 使用ir并jc直接代替不太紧凑的行 - 列对.

  • 如果[`mxCreateDoubleMatrix`](http://www.mathworks.com/help/matlab/apiref/mxcreatedoublematrix.html)在尝试分配时内存不足,它只会终止MEX文件并将控制返回给MATLAB,所以很遗憾你将没有机会检查`NULL` @GarimaSingh在发布后续内容之前,请尽量使用稀疏的帮助函数. (2认同)