使用 mex 将一个大矩阵从 Matlab 传递到 C:Matlab 崩溃

Posted

技术标签:

【中文标题】使用 mex 将一个大矩阵从 Matlab 传递到 C:Matlab 崩溃【英文标题】:Passing a big matrix from Matlab to C using mex: Matlab crashes 【发布时间】:2015-02-09 13:33:20 【问题描述】:

我编写了一个 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.

这是我的 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);

这是我的墨西哥代码

  #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

  

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

[rows cols values] = find(smA_System);
[nrows ncols] = size(smA_System);

然后,将指针传递给行、列、值。

【问题讨论】:

【参考方案1】:

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

更新:

最佳做法是将稀疏矩阵按原样传递给您的 mex 代码。 在你的 mex 函数中,你应该:

    验证输入确实是稀疏的,如预期的那样。见mxIsSparse。 使用mxGetIrmxGetJcmxGetPr 获取三个相关指针(四个用于复矩阵)。 直接使用 irjc,而不是不太紧凑的行列对。

【讨论】:

谢谢。我对使用 mex 传递稀疏矩阵还有其他问题。请参阅我的问题的更新部分。如果您也能回答这个问题,我将不胜感激。 @GarimaSingh 你应该问一个新问题而不是改变你的问题 如果 mxCreateDoubleMatrix 在尝试分配时内存不足,它只会终止 MEX 文件并将控制权返回给 MATLAB,因此很遗憾您将没有机会检查 NULL @GarimaSingh在发布后续内容之前,请尽最大努力使用稀疏辅助函数。 @chappjc 你可能是对的。我不记得曾经在 mex 文件中获得过“out-of-mem”...

以上是关于使用 mex 将一个大矩阵从 Matlab 传递到 C:Matlab 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何传递 matlab::data::TypedArray<double> 作为指针在 MATLAB mex 文件中构造犰狳矩阵?

在 MATLAB 中使用 MEX 文件访问存储在元胞数组中的矩阵

MEX 文件中 Matlab 矩阵的线性索引

如何从 mex 函数返回矩阵结构?

如何逐行读取 Matlab mex 函数的输入矩阵?

如何逐行读取 Matlab mex 函数的输入矩阵?