How Do I use Mexcallmatlab to Call a User-defined function? - matlab

I am trying to parallelize a section of my Matlab code using OpenMP in a mex file. The section in theMatlab code that I want to parallelize is:
for i = 1 : n
D(:, i) = CALC(A, B(:,i), C(i));
end
I have written this in order to parallelize it:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
size_t r,n,i,G;
double *A, *B, *C, *D;
int nthreads;
nthreads = 4;
A = mxGetPr(prhs[0]); /* first input matrix */
B = mxGetPr(prhs[1]); /* second input matrix */
C = mxGetPr(prhs[2]);/* third input matrix */
/* dimensions of input matrices */
r = mxGetN(prhs[0]);
n = mxGetN(prhs[1]);
plhs[0] = mxCreateDoubleMatrix(r,n, mxREAL);
D = mxGetPr(plhs[0]);
G=n/nthreads;
omp_set_num_threads(nthreads);
#pragma omp parallel for schedule (dynamic, G)
{
for i = 1 : n
D(:, i) = CALC(A, B(:,i), C(i));
}
}
CALC is a Matlab function I have written. My challenge is how to use Mexcallmatlab to call in the CALC function to the mex file so that it can execute it in parallel inside my mex file, and return the elements of each column of D (i.e. D(:, i) back to my Matlab code.
Sorry for the lenghty question. Any help I can get on this will be highly appreciated.

You need to use multiple MATLAB processes to be able to run multiple calls in parallel. The easiest way would be to use parallel computing toolbox and use parfor instead of for loop.

Related

Reduce size of vector in MEX-file

Given a typed vector like this
matlab::data::ArrayFactory Factory;
matlab::data::TypedArray<double> BigArray = Factory.createArray({420, 1});
How can I shrink BigArray size without (re)allocations? All I want is to set its internal length-dimension to a value smaller than 420.
Well supposing you spring for the C API instead of the C++ API, you can use mxSetN or mxSetM on the mxArray object to reduce it.
int M = 420;
int N = 1;
mxArray *BigArray = mxCreateNumericMatrix(M, N, mxDOUBLE_CLASS, mxREAL);
mxSetM(BigArray, M - 4);

Matlab crashing on passing large array to Mex file

I am trying to write a wrapper for the LibIGL Normal functions. But so far I have managed to crash Matlab everytime I call the mex function with a large array. So I went back to try write a function that just returns one of the inputs as the output. The output works, but only if it is a small array. When I try to pass a large array (like 53490x3), Matlab crashes.
I looked at the other questions open, and tried the solutions, but the problem persists.
My code is as follows:
#include <mex.h>
#include <igl\per_vertex_normals.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
using namespace Eigen;
int row = mxGetM(prhs[0]);
int col = mxGetN(prhs[0]);
int row2 = mxGetM(prhs[1]);
int col2 = mxGetN(prhs[1]);
int outRow = row;
int outCol = col;
Map<MatrixXd> V(mxGetPr(prhs[0]), row, col);
Map<MatrixXd> F(mxGetPr(prhs[1]), row2, col2);
if (nrhs != 2)
{
mexErrMsgIdAndTxt("MATLAB:mexcpp:nargin", "vertex normal function requires 2 inputs, the vertices and the faces to calculate upon.");
}
mwSize rows = V.rows();
mwSize cols = V.cols();
plhs[0] = mxCreateDoubleMatrix(rows, cols, mxREAL);
Map<MatrixXd> map(mxGetPr(plhs[0]), rows, cols);
map = V;
return;
}
From my time that I spent with it, seems like crash happens when I am trying to access the V matrix to fill up the output. So it is some kind of invalid memory access (which is what the error says) that is happening. But I am not sure about how to get this working. What I would ideally want is to take the two matrix as input and calculate a result which would be another Eigen matrix and return that as the output.
Two suggestions:
You might be overflowing row, col, row2, col2. Change them from int to mwSize. Unlikely to be a problem, but it will be machine dependent you don't mention your setup. You can check limits.h for INT_MAX which is normally plenty, but mwSize is safest. Output them with mexPrintf to make sure they are what you expect.
You might be out of memory. Check that plhs[0] is not NULL. Should not be a problem for 53490x3.

How to do Weighted Averaging of n conscutive values in an Array

I have a 900×1 vector of values (in MATLAB). Each 9 consecutive values should be averaged -without overlap- result in a 100×1 vector of values. The problem is that the averaging should be weighted based on a weighting vector of [1 2 1;2 4 2;1 2 1]. Is there any efficient way to do that averaging? I’ve heard about conv function in MATLAB; Is it helpful?
conv works by sliding a kernel through your data. But in your case, you need the mask to be jumping through your data, so I don't think conv will work for you.
If you want to use existing MATLAB function, you can do this (I have to assume your weighting matrix has only one dimension) :
kernel = [1;2;1;2;4;2;1;2;1];
in_matrix = reshape(in_matrix, 9, 100);
base = sum(kernel);
out_matrix = bsxfun(#times, in_matrix, kernel);
result = sum(out_matrix,1)/base;
I don't know if there is any clever way to speed this up. bsxfun allows singleton expansion, but maybe not dimension reduction.
A faster way would be to use mex. Open a new file in editor, paste the following code and save file as weighted_average.c.
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *in_matrix, *kernel, *out_matrix, base;
int niter;
size_t nrows_data, nrows_kernel;
/* Get number of element along first dimension of input matrix. */
nrows_kernel = mxGetM(prhs[1]);
nrows_data = mxGetM(prhs[0]);
/* Create output matrix*/
plhs[0] = mxCreateDoubleMatrix((mwSize)nrows_data/nrows_kernel,1,mxREAL);
/* Get a pointer to the real data */
in_matrix = mxGetPr(prhs[0]);
kernel = mxGetPr(prhs[1]);
out_matrix = mxGetPr(plhs[0]);
/* Sum the elements in weighting array */
base = 0;
for (int i = 0; i < nrows_kernel; i +=1)
{
base += kernel[i];
}
/* Perform calculation */
niter = nrows_data/nrows_kernel;
for (int i = 0; i < niter ; i += 1)
{
for (int j = 0; j < nrows_kernel; j += 1)
{
out_matrix[i] += in_matrix[i*nrows_kernel+j]*kernel[j];
}
out_matrix[i] /= base;
}
}
Then in command window , type in
mex weighted_average.c
To use it:
result = weighted_average(input, kernel);
Note that both input and kernel have to be M x 1 matrix. On my computer, the first method took 0.0012 second. The second method took 0.00007 second. That's an order of magnitude faster than the first method.

Run time bug on matlab MEX file

I have struggling with an implementation of MEX file, I get run time error!
I would like to given two inputs : inMatToInv, inMatToMul I would like to compute : inv(inMatToInv)*inMatToMul, I assume that the user enters only 3x3 matrices.
I also assume that the inMatToInv in invertible.
/*==========================================================
* inv_and_mul_3by3.c
* inverse 3x3 matrix and multiply it by another 3x3 matrix
* The calling syntax is: outMatrix = (mat_to_inv,mat_to_mul)
*========================================================*/
#include "mex.h"
/* The computational routine */
void inv_and_mul_3by3(double *mat_to_inv, double *mat_to_mul, double *out)
{
// Description : out = inv(mat_to_inv)*mat_to_mul
double *inversed;
double det;
/* Calculate the matrix deteminant */
det = mat_to_inv[0]*(mat_to_inv[4]*mat_to_inv[8]-mat_to_inv[7]*mat_to_inv[5]) - mat_to_inv[3]*(mat_to_inv[1]*mat_to_inv[8]-mat_to_inv[7]*mat_to_inv[2])+mat_to_inv[6]*(mat_to_inv[1]*mat_to_inv[5]-mat_to_inv[4]*mat_to_inv[2]);
// Calcualte the inversed matrix
inversed[0] = (mat_to_inv[4]*mat_to_inv[8] - mat_to_inv[7]*mat_to_inv[5])/det;
inversed[3] = (mat_to_inv[6]*mat_to_inv[5] - mat_to_inv[3]*mat_to_inv[8])/det;
inversed[6] = (mat_to_inv[3]*mat_to_inv[7] - mat_to_inv[6]*mat_to_inv[4])/det;
inversed[1] = (mat_to_inv[7]*mat_to_inv[2] - mat_to_inv[1]*mat_to_inv[8])/det;
inversed[4] = (mat_to_inv[0]*mat_to_inv[8] - mat_to_inv[6]*mat_to_inv[2])/det;
inversed[7] = (mat_to_inv[6]*mat_to_inv[1] - mat_to_inv[0]*mat_to_inv[7])/det;
inversed[2] = (mat_to_inv[1]*mat_to_inv[5] - mat_to_inv[4]*mat_to_inv[2])/det;
inversed[5] = (mat_to_inv[3]*mat_to_inv[2] - mat_to_inv[0]*mat_to_inv[5])/det;
inversed[8] = (mat_to_inv[0]*mat_to_inv[4] - mat_to_inv[3]*mat_to_inv[1])/det;
out[0] = inversed[0]*mat_to_mul[0] + inversed[3]*mat_to_mul[1] + inversed[6]*mat_to_mul[2];
out[1] = inversed[1]*mat_to_mul[0] + inversed[4]*mat_to_mul[1] + inversed[7]*mat_to_mul[2];
out[2] = inversed[2]*mat_to_mul[0] + inversed[5]*mat_to_mul[1] + inversed[8]*mat_to_mul[2];
out[3] = inversed[0]*mat_to_mul[3] + inversed[3]*mat_to_mul[4] + inversed[6]*mat_to_mul[5];
out[4] = inversed[1]*mat_to_mul[3] + inversed[4]*mat_to_mul[4] + inversed[7]*mat_to_mul[5];
out[5] = inversed[2]*mat_to_mul[3] + inversed[5]*mat_to_mul[4] + inversed[8]*mat_to_mul[5];
out[6] = inversed[0]*mat_to_mul[6] + inversed[3]*mat_to_mul[7] + inversed[6]*mat_to_mul[8];
out[7] = inversed[1]*mat_to_mul[6] + inversed[4]*mat_to_mul[7] + inversed[7]*mat_to_mul[8];
out[8] = inversed[2]*mat_to_mul[6] + inversed[5]*mat_to_mul[7] + inversed[8]*mat_to_mul[8];
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double *inMatToInv; /* 3x3 input matrix that is inversed */
double *inMatToMul; /* 3x3 input matrix that multiply the inversed matrix*/
double *outMatrix; /* 3x3 output matrix */
/* create pointers to the real data in the input matrix */
inMatToInv = mxGetPr(prhs[0]);
inMatToMul = mxGetPr(prhs[1]);
/* create the output matrix */
plhs[0] = mxCreateDoubleMatrix(3,3,mxREAL);
/* get a pointer to the real data in the output matrix */
outMatrix = mxGetPr(plhs[0]);
/* call the computational routine */
inv_and_mul_3by3(inMatToInv,inMatToMul,outMatrix);
}
any help will be much appreciated.
Thanks,
Tamir
You declare a pointer double *inversed, but you do not allocate any memory for it. So when you access inversed[0] you get an error. Try:
double inversed[9];
I'd recommend using the blas and lapack interface for matrix operations in a C mex file. Have a look at Mathworks documentation on doing this here.
You would be interested in the lapack routines dgetrf and dgetri for the matrix inversion and dgemm for matrix multiplication. The lapack interface can be really messy and difficult to grasp but there are lots of references online about them. For example, this stack overflow Q/A.

Matlab FFT and FFTW

I'm trying to have the same FFT with FFTW and Matlab. I use MEX files to check if FFTW is good. I think I have everything correct but :
I get absurd values from FFTW,
I do not get the same results when running the FFTW code several times on the same input signal.
Can someone help me get FFTW right?
--
EDIT 1 : I finally figured out what was wrong, BUT...
FFTW is very unstable : I get the right spectrum 1 time out of 5 !
How come? Plus, when I get it right, it doesn't have symmetry (which is not a very serious problem but that's too bad).
--
Here is the Matlab code to compare both :
fs = 2000; % sampling rate
T = 1/fs; % sampling period
t = (0:T:0.1); % time vector
f1 = 50; % frequency in Hertz
omega1 = 2*pi*f1; % angular frequency in radians
phi = 2*pi*0.25; % arbitrary phase offset = 3/4 cycle
x1 = cos(omega1*t + phi); % sinusoidal signal, amplitude = 1
%%
mex -I/usr/local/include -L/usr/local/lib/ -lfftw3 mexfftw.cpp
N=256;
S1=mexfftw(x1,N);
S2=fft(x1,N);
plot(abs(S1)),hold,plot(abs(S2),'r'), legend('FFTW','Matlab')
Here is the MEX file :
/*********************************************************************
* mex -I/usr/local/include -L/usr/local/lib/ -lfftw3 mexfftw.cpp
* Use above to compile !
*
********************************************************************/
#include <matrix.h>
#include <mex.h>
#include "fftw3.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
//declare variables
mxArray *sig_v, *fft_v;
int nfft;
const mwSize *dims;
double *s, *fr, *fi;
int dimx, dimy, numdims;
//associate inputs
sig_v = mxDuplicateArray(prhs[0]);
nfft = static_cast<int>(mxGetScalar(prhs[1]));
//figure out dimensions
dims = mxGetDimensions(prhs[0]);
numdims = mxGetNumberOfDimensions(prhs[0]);
dimy = (int)dims[0]; dimx = (int)dims[1];
//associate outputs
fft_v = plhs[0] = mxCreateDoubleMatrix(nfft, 1, mxCOMPLEX);
//associate pointers
s = mxGetPr(sig_v);
fr = mxGetPr(fft_v);
fi = mxGetPi(fft_v);
//do something
double *in;
fftw_complex *out;
fftw_plan p;
in = (double*) fftw_malloc(sizeof(double) * dimy);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * nfft);
p = fftw_plan_dft_r2c_1d(nfft, s, out, FFTW_ESTIMATE);
fftw_execute(p); /* repeat as needed */
for (int i=0; i<nfft; i++) {
fr[i] = out[i][0];
fi[i] = out[i][1];
}
fftw_destroy_plan(p);
fftw_free(in);
fftw_free(out);
return;
}
Matlab uses the fftw library to perform its ffts, on my platform (Mac OS) this leads to issues with the linker as mex replaces the desired library with Matlab's version of fftw. To avoid this static link to the library using mex "-I/usr/local/include /usr/local/lib/libfftw3.a mexfftw.cpp".
The input of fftw_plan_dft_r2c_1d is not destroyed so you don't need to duplicate the input (note: not true for fftw_plan_dft_c2r_1d). The output has size nfft/2+1 as the output of a real fft is Hermitian. So to get the full output use:
for (i=0; i<nfft/2+1; i++) {
fr[i] = out[i][0];
fi[i] = out[i][1];
}
for (i=1; i<nfft/2+1; i++) {
fr[nfft-i] = out[i][0];
fi[nfft-i] = out[i][1];
}
Should "p = fftw_plan_dft_r2c_1d(nfft, s, out, FFTW_ESTIMATE);"
be
"p = fftw_plan_dft_r2c_1d(nfft, in, out, FFTW_ESTIMATE);".
'in' is 16-byte aligned, but 's' may not.
I am not sure whether it will cause a problem. I have a similar code about FFTW,
it sometimes gives me correct result and other times NaN. Also, I tried to test
my code with python ctypes, and actually it has the same weired behavior.
Finally, I found this post Checking fftw3 with valgrind, and it helps me.
For me, the issue is the reservation of heap storage in FFTW which are not freed
even after the program terminates.
fftw_cleanup()
resolves my problem. Maybe it can help you too.