Передача большой матрицы из Matlab в C с использованием mex: Matlab вылетает

0

Я написал код mex, который отправляет скаляр и матрицу в C-код из кода matlab. Он отлично работает с меньшей матрицей. Однако, когда я пытаюсь передать большую разреженную матрицу (размер ~ 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);

Вот мой код 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);

а затем передать указатель на строки, столбцы, значения.

Теги:
matrix
mex

1 ответ

6
Лучший ответ

Как вы указали на свой вопрос, ваш код подходит только для чтения full матриц в качестве второго аргумента. Когда prhs[1] является разреженной матрицей, вы больше не можете обращаться к ней как к полной матрице, используя *(y+count): это SPARSE, она не занимает n в памяти, а гораздо меньше.
Чтобы получить доступ к элементам разреженной матрицы в mex, вы должны использовать mxGetIr и mxGetJc. То, как Matlab магазины разреженная матрица лучше всего объясняется здесь.
Более того, ваша матрица ввода является разреженной, пока ваша матрица вывода заполнена - это может вызвать ошибку при отсутствии памяти при попытке выделить выходную матрицу. Тем не менее, вы не проверяете plhs[0] возвращенный из mxCreateDoubleMatrix(mrows,ncols, mxREAL); он, скорее всего, будет NULL.

Обновить:

Лучшая практика состоит в том, чтобы передать разреженную матрицу в ваш код mex как есть.
В вашей mex-функции вы должны:

  1. Убедитесь, что вход действительно разрежен, как и ожидалось. См. mxIsSparse.
  2. Получите три соответствующих указателя (четыре для сложных матриц), используя mxGetIr, mxGetJc и mxGetPr.
  3. Работайте с ir и jc напрямую, а не пар строк строки, которые менее компактны.
  • 0
    Благодарю. У меня есть дополнительный вопрос о передаче разреженной матрицы с помощью mex. Пожалуйста, смотрите обновленную часть моего вопроса. Буду признателен, если вы ответите также.
  • 1
    @GarimaSingh Вы, вероятно, должны задать новый вопрос, а не менять свой вопрос
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню