Mex 编译函数,用于计算集合交集和差异,不断崩溃
Posted
技术标签:
【中文标题】Mex 编译函数,用于计算集合交集和差异,不断崩溃【英文标题】:Mex compiled function, used to compute set intersection and difference, keeps crashing 【发布时间】:2015-06-11 10:22:41 【问题描述】:[这个问题已经解决]
(这个问题已经发布在 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
【问题讨论】:
如果已解决,请在此处发布答案,并接受它;) 嗨。 setdiff 函数呢? 【参考方案1】:如果您能提供来自 OS X 的错误消息会更好,可以通过点击屏幕右上角的Crashed通知来获得。对于涉及诸如 C 之类的一些低级(与 Matlab 本身相比)东西的问题,来自操作系统的崩溃报告通常很有用,因为您可以看到程序崩溃的原因。您可以将其完整粘贴到 pastebin 或其他任何内容中。
如果您确实发现它在您的代码中崩溃,请将-g
标志添加到clang
,以便您可以在崩溃报告中获得一些行号。
很抱歉没有写这篇评论——我还没有 50 个代表。
【讨论】:
嗨。感谢您的回答。实际上,错误消息并不总是相同的。但要么是 Matlab 冻结,要么我收到一条消息,如“Matlab 遇到内部问题,需要关闭”。我编辑了我的原始消息并从 Matlab 上传了崩溃文件。这显然是一个分段违规,但我不知道在哪里.. 该死,我太笨了。我在数组初始化中输入了错误的大小......我更正了帖子。以上是关于Mex 编译函数,用于计算集合交集和差异,不断崩溃的主要内容,如果未能解决你的问题,请参考以下文章