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