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

Passing a big matrix from Matlab to C using mex: Matlab crashes

本文关键字:Matlab 崩溃 mex 一个 使用      更新时间:2023-10-16

我写了一个mex代码,它从matlab代码向C代码发送标量和矩阵。它适用于较小的矩阵。然而,当我试图通过大型稀疏矩阵(大小~8448x3264)时,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);

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

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

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

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

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

更新:

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

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