Hello,
I am going over an example I got out of a book. The example shows one way of MEXing the following code:
function [c] = countm(A,B)
% Count the number of times elements of A appear in B.
c = zeros(size(A));
for ii = 1:numel(A)
c(ii) = sum(abs(A(ii)B(:)) < eps);
end
The point of this thread isn't to optimize this Matlab code, I put the Matlab version in here so an experienced Matlaber can tell at a glance what is going on with the MEXFile....
The MEXFile that the author shows is much slower than the Matlab code, so I tried to speed it up by changing some things. I found that the main source of drag is from using the fabs function from the math C++ library. Here are timing results with his code as is:
N = 120;
a = round(rand(N)*10);
b = round(rand(N)*10);
tic,cpp = count(a,b);toc % The c++ code is called count.cpp
Elapsed time is 11.867683 seconds. % WOW!!
tic,mtlb = countm(a,b);toc
Elapsed time is 3.743850 seconds.
And here is the MEXFile
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#include <math.h>
#include "mex.h"
#define A prhs[0] /* Pointer to first righthandside argument */
#define B prhs[1] /* Pointer to second righthandside argument */
#define TOL prhs[2] /* Pointer to third righthandside argument */
#define C plhs[0] /* Pointer to first lefthandside argument */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
int i, j, sizea, sizeb;
double tol, vcount;
double *a, *b, *c;
/* Do some error checking */
if (nrhs < 2)
mexErrMsgTxt("Missing input arguments.");
else if (nrhs > 3)
mexErrMsgTxt("Too many input arguments.");
else if (nlhs > 1)
mexErrMsgTxt("Too many output arguments.");
/* Get tolerance value if supplied, otherwise use EPS. */
if (nrhs == 3) {
if (!mxIsNumeric(TOL)  mxIsComplex(TOL) 
mxGetNumberOfElements(TOL) != 1 )
mexErrMsgTxt("TOL must be a real numeric scalar.");
tol = mxGetScalar(TOL);
if (tol < mxGetEps())
mexErrMsgTxt("TOL must be a positive value.");
}
else
tol = mxGetEps();
/* Make sure input arrays are noncomplex numeric arrays. */
if (!mxIsNumeric(A)  !mxIsNumeric(B) 
mxIsComplex(A)  mxIsComplex(B))
mexErrMsgTxt("Input arguments must be real of type double.");
/* Create the output mxArray the same size as A */
C = mxCreateNumericArray(mxGetNumberOfDimensions(A),
mxGetDimensions(A), mxDOUBLE_CLASS, mxREAL);
/* Get the number of elements in A and B and create pointers */
/* to the input and output arrays. */
sizea = mxGetNumberOfElements(A);
sizeb = mxGetNumberOfElements(B);
a = (double *) mxGetPr(A);
b = (double *) mxGetPr(B);
c = (double *) mxGetPr(C);
/* Cycle through the elements of the arrays and count values */
for (i = 0; i < sizea; i++)
{
vcount = 0.0;
for (j = 0; j < sizeb; j++)
// We can either use the next two lines, or everyting between
// the next set of braces. Must uncomment include math.h above.
if ((fabs(a[i]  b[j])) <= tol)
vcount++;
// { // For the math library version, use above two lines instead.
// if (a[i]>b[j])
// {
// if (a[i]b[j] < tol)
// vcount++;
// }
// else
// {
// if (b[j]a[i] < tol)
// vcount++;
// }
// } // This is the matching brace for the above comment.
c[i] = vcount;
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
When I took out the include <math.h>, and used the lines that are commented instead of the fabs call at the end of the function, I got some different timings. Here they are:
Elapsed time is 1.171837 seconds. % Borland Compiler (LCC gives 2.3 seconds)
Elapsed time is 3.770942 seconds.
So my question is this: Is the price for using standard functions always so high? I was expecting a little bit of difference, but not that much. So what is going on here?
By the way, this is out of Mastering Matlab 7.
Thanks.
