[这个问题已经解决]
(这个问题已经发布在Matlab论坛上,在这里:http://www.mathworks.com/matlabcentral/answers/223415-mex-compiled-function-used-to-compute-set-intersection-and-difference-keeps-crashing)
嗨,大家好,
我正在尝试构建一个非常简单的函数,它应该计算两组的“交集”和“差异”,返回相应的索引。
例如,如果我们有
in1 = [1 2 4 5 9]
in2 = [2 3 4 8]
它应该返回
common1 = [2 3] % since all(in1(common1) == in2(common2))
common2 = [1 3]
only1 = [1 4 5] % the remaining indices, not in common1
only2 = [2 4] % the ones not in common2
我可以使用intersect和setdiff来做到这一点,但因为我有小集,因为我将这个函数称为数千次,我认为使用编译的C-mex文件来做这应该是最快的方法。它确实是我算法的瓶颈。
我编写了这个函数
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
mexPrintf("Starting ...\n") ;
/* Check nbr of inputs and outputs */
if (nrhs != 2 || nlhs != 4)
mexErrMsgTxt("intersectFast needs 4 outputs and 2 inputs") ;
const mxArray* pin1 = prhs[0] ;
const mxArray* pin2 = prhs[1] ;
/* Inputs should be column vectors */
if (mxGetN(pin1) != 1 || mxGetN(pin2) != 1)
mexErrMsgTxt("inputs arguments should be column vectors") ;
mwSize dims1 = mxGetM(pin1) ;
mwSize dims2 = mxGetM(pin2) ;
double* in1 = mxGetPr(pin1) ;
double* in2 = mxGetPr(pin2) ;
mexPrintf("Checks passed\n") ;
mwIndex* idCommon1 = mxCalloc(dims1, sizeof(mwIndex)) ; // At most dims1 elements
mwIndex* idCommon2 = mxCalloc(dims2, sizeof(mwIndex)) ; /* AT MOST dims2 and NOT dims1 ... this was the error. Damn I feel so stupid right now. */
mwIndex* idOnly1 = mxCalloc(dims1, sizeof(mwIndex)) ; /* Same error here */
mwIndex* idOnly2 = mxCalloc(dims2, sizeof(mwIndex)) ;
mwSize sizeCommon1, sizeCommon2, sizeOnly1, sizeOnly2 ;
mwIndex i, j ;
mwIndex k, l ;
int match ;
/* Intersect fast */
/* in1 */
k = 0 ; l = 0 ;
for(i = 0 ; i < dims1 ; i++) {
match = 0 ;
for(j = 0 ; j < dims2 ; j++) {
if (in1[i] == in2[j]) {
idCommon1[k++] = (i+1) ; /* Matlab <-> C convention */
match = 1 ;
break ;
}
}
if (! match) {
idOnly1[l++] = (i+1) ;
}
}
sizeCommon1 = k ;
sizeOnly1 = l ;
/* in2 */
k = 0 ; l = 0 ;
for(i = 0 ; i < dims2 ; i++) {
match = 0 ;
for(j = 0 ; j < dims1 ; j++) {
if (in2[i] == in1[j]) {
idCommon2[k++] = (i+1) ;
match = 1 ;
break ;
}
}
if (! match)
idOnly2[l++] = (i+1) ;
}
sizeCommon2 = k ;
sizeOnly2 = l ;
/* Return results */
mexPrintf("Sizes = %d, %d, %d, %d\n", sizeCommon1, sizeCommon2, sizeOnly1, sizeOnly2) ;
plhs[0] = mxCreateNumericMatrix(sizeCommon1, 1, mxUINT32_CLASS, mxREAL);
plhs[1] = mxCreateNumericMatrix(sizeCommon2, 1, mxUINT32_CLASS, mxREAL);
plhs[2] = mxCreateNumericMatrix(sizeOnly1, 1, mxUINT32_CLASS, mxREAL);
plhs[3] = mxCreateNumericMatrix(sizeOnly2, 1, mxUINT32_CLASS, mxREAL);
if (plhs[0] == NULL || plhs[1] == NULL || plhs[2] == NULL || plhs[3] == NULL)
mexErrMsgTxt("Could not create mxArray.\n");
mxSetData(plhs[0], idCommon1);
mxSetData(plhs[1], idCommon2);
mxSetData(plhs[2], idOnly1);
mxSetData(plhs[3], idOnly2);
mexPrintf("Done.\n") ;
}
当我测试它时,它经常有效,但它总是最终崩溃......例如,使用
% Test intersect fast
clc ; close all ; clear all ;
while true
clc ;
id1 = unique(randi(10, 8, 1)) ;
id2 = unique(randi(12, 6, 1)) ;
[idCommon1, idCommon2, idOnly1, idOnly2] = intersectFast(id1, id2) ;
pause(0.1)
end
完成mex功能后,它总会在某些时候崩溃。我的意思是我得到一个错误,如“Matlab遇到内部问题,需要关闭”。所以我猜mxCreateNumericMatrix或mxSetData都有问题,但我无法弄清楚究竟是什么问题。我尝试更改索引类型(uint32,uint64,int,...)但它并没有真正改变任何东西。
我在OSX 10.10.3上使用R2015a,编译是默认的(Clang)。
非常感谢你的帮助!
=================
编辑:让我更具体地讲述它是如何崩溃的。 有时候,MATLAB才开始冻结(我得到旋转的彩色鼠标指针......),并最终崩溃。在这种情况下,我需要强制MATLAB退出。 在其他一些时候,我从MATLAB收到一条错误消息,说它遇到内部错误并需要退出。在这种情况下,我可以找到一个Matlab崩溃文件。我在此处上传了一份崩溃报告:http://pastebin.com/ry7MN7yw答案 0 :(得分:0)
如果您可以从OS X提供错误消息会更好,可以通过单击屏幕右上角的已崩溃通知来获取。对于涉及某些低级(与Matlab本身相比)的问题,例如C,来自操作系统的崩溃报告通常很有用,因为您可以看到崩溃程序的原因。您可以将其全部粘贴到pastebin或其他任何内容。
如果您确实发现它在代码中崩溃,请将-g
标记添加到clang
,以便在崩溃报告中获取一些行号。
很抱歉没有将此作为评论 - 我还没有50个代表。