使用 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 中稀疏矩阵的元素,您应该使用 mxGetIr
和 mxGetJc
。 Matlab 存储稀疏矩阵的方式最好解释here。
此外,您的输入矩阵是稀疏的,而您的输出矩阵已满 - 这可能会在尝试分配输出矩阵时导致内存不足错误。但是,您没有检查从mxCreateDoubleMatrix(mrows,ncols, mxREAL);
返回的plhs[0]
,它很可能是NULL
。
更新:
最佳做法是将稀疏矩阵按原样传递给您的 mex 代码。 在你的 mex 函数中,你应该:
-
验证输入确实是稀疏的,如预期的那样。见
mxIsSparse
。
使用mxGetIr
、mxGetJc
和mxGetPr
获取三个相关指针(四个用于复矩阵)。
直接使用 ir
和 jc
,而不是不太紧凑的行列对。
【讨论】:
谢谢。我对使用 mex 传递稀疏矩阵还有其他问题。请参阅我的问题的更新部分。如果您也能回答这个问题,我将不胜感激。 @GarimaSingh 你应该问一个新问题而不是改变你的问题 如果mxCreateDoubleMatrix
在尝试分配时内存不足,它只会终止 MEX 文件并将控制权返回给 MATLAB,因此很遗憾您将没有机会检查 NULL
@GarimaSingh在发布后续内容之前,请尽最大努力使用稀疏辅助函数。
@chappjc 你可能是对的。我不记得曾经在 mex 文件中获得过“out-of-mem”...以上是关于使用 mex 将一个大矩阵从 Matlab 传递到 C:Matlab 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
如何传递 matlab::data::TypedArray<double> 作为指针在 MATLAB mex 文件中构造犰狳矩阵?