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 编译函数,用于计算集合交集和差异,不断崩溃的主要内容,如果未能解决你的问题,请参考以下文章

在 C Mex-File 中使用 BLAS 库

从 Matlab 调用的 Mex 函数和数值差异

R调用的C代码不断崩溃

多线程 (pthreads) MATLAB mex 函数导致 MATLAB 在退出后崩溃

matlab中用于mex函数的安全、快速的CFLAGS

防止 MEX 文件在 MATLAB 中崩溃