Editing elements of vector inside mex function slow
Show older comments
Consider the following mex function written in C, which returns a column vector:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int x = *mxGetPr(prhs[0]);
int length = *mxGetPr(prhs[1]);
plhs[0] = mxCreateDoubleMatrix(x, 1, mxREAL);
double *output_vector = mxGetPr(plhs[0]);
int i;
for(i = 0; i < length; ++i) {
output_vector[i % x] += 1;
}
}
If I compile this code in Matlab and then run the function with inputs (5, 1000000000), it takes 3.228 s. Consider now the following altered code:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int x = *mxGetPr(prhs[0]);
int length = *mxGetPr(prhs[1]);
plhs[0] = mxCreateDoubleMatrix(x, 1, mxREAL);
//double *output_vector = mxGetPr(plhs[0]);
double *output_vector = malloc(x*sizeof(double));
int i;
for(i = 0; i < length; ++i) {
output_vector[i] = 0.0;
}
for(i = 0; i < length; ++i) {
output_vector[i % x] += 1;
}
free(output_vector);
}
If I compile and run the function with the same inputs as before, it takes only 0.627 s.
It seems like editing elements of an mxArray is much slower than editing elements of a double array. It seems like there should be no issues with MATLABs column-major order vs the row-major order in C since I am only using a vector here.
Any ideas why I am seeing this time difference?
Here is some further information:
- OS: 64-bit Windows 10.
- Compiler: MinGW64 Compiler (C), with the additional compile flags -std=c99 and -pedantic.
- MATLAB version: R2016b
Update: For the simple example above, updating the mxArray takes about 5 times as long. In another code which I am using for an actual application, updating an mxArray instead of a double array takes 30 times as long.
Update 2: Please see my new timings in my comment below after incorporating the helpful suggestions by Walter and James. After fixing an error in the second code above, writing to an mxArray is now 10x slower than a double array for this simple example.
4 Comments
Walter Roberson
on 26 Feb 2018
Edited: Walter Roberson
on 26 Feb 2018
You should consider using memset() or calloc() instead of looping setting zero.
You should also take a look at the implementation of https://www.mathworks.com/matlabcentral/fileexchange/31362-uninit-create-an-uninitialized-variable--like-zeros-but-faster- in the sense that it would give you a better comparison for the speed of MATLAB allocation compared to malloc(), in that the time of any zeroing of the memory would be factored out.
James Tursa
on 26 Feb 2018
Edited: James Tursa
on 26 Feb 2018
How does this not crash MATLAB?
double *output_vector = malloc(x*sizeof(double));
int i;
for(i = 0; i < length; ++i) {
output_vector[i] = 0.0;
}
If x is 5 and length is 1000000000 the above code is writing off the end of the allocated memory block big time and should crash. Are you sure this is the actual code you are running and comparing?
Also, how are you calculating the timing? Average of multiple runs after mex routine is loaded? tic & toc?
Osman Malik
on 26 Feb 2018
Walter Roberson
on 26 Feb 2018
Next step: try with an uninit MATLAB array followed by writing in zeros. This will give you information about the amount of time it takes to go through the MATLAB memory manager.
Accepted Answer
More Answers (0)
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!