Clear Filters
Clear Filters

Mex compiled function, used to compute set intersection and difference, keeps crashing

4 views (last 30 days)
Hi Guys,
I'm trying to build a very simple function that is supposed to computed the "intersection" and "difference" of two sets, returning the corresponding indices.
For instance, if we have
in1 = [1 2 4 5 9]
in2 = [2 3 4 8]
it should return
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
I could do that using intersect and setdiff, but because I have small sets and since I call this function thousands of times, I think doing it using a compiled C-mex file should be the fastest way. It really is the bottleneck of my algorithm at the moment.
I coded this function
#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(dims1, sizeof(mwIndex)) ;
mwIndex* idOnly1 = mxCalloc(dims2, sizeof(mwIndex)) ;
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") ;
}
When I test it, it often works, but it always eventually crashes ... For instance, using
% 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.01)
end
it always crashes at some point, after the mex function is done. What I mean is that I get an error like "Matlab stopped working ...". So I guess there is some problem with either the mxCreateNumericMatrix or the mxSetData, but I can't figure out what is the problem exactly. I tried changing the index types (uint32, uint64, int, ...) but it did not really change anything.
I am using R2015a on OSX 10.10.3 and the compiled is the default one (Clang).
Thanks a lot for your help !

Answers (2)

Titus Edelhofer
Titus Edelhofer on 11 Jun 2015
Hi,
I'm not 100% sure why it crashes, but that's at least a good way to create memory leaks ;-).
You should replace the mxSetData calls by calls to memcpy:
memcpy(mxGetData(plhs[0]), idCommon1, sizeCommon1 * sizeof(mwIndex));
Second, to be prepared when using 64Bit integers for mwIndex, I would be careful when creating the return arguments, maybe something like
if (sizeof(mwIndex)==64) {
plhs[0] = mxCreateNumericMatrix(sizeCommon1, 1, mxUINT64_CLASS, mxREAL);
}
else {
plhs[0] = mxCreateNumericMatrix(sizeCommon1, 1, mxUINT32_CLASS, mxREAL);
}
Hope this helps,
Titus

Léopold Cambier
Léopold Cambier on 11 Jun 2015
Hello Titus
Thanks for your answer. It turned out that the error was a *** "size-error" in arrays allocations ... The dimensions should be swapped in the following two lines mwIndex* idCommon2 = mxCalloc(dims1, sizeof(mwIndex)) ; mwIndex* idOnly1 = mxCalloc(dims2, sizeof(mwIndex)) ;
But thanks for your advices, I'll take that into account :)

Categories

Find more on MATLAB Compiler in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!