Editing elements of vector inside mex function slow
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Osman Malik
le 26 Fév 2018
Commenté : James Folberth
le 27 Fév 2018
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 commentaires
Walter Roberson
le 26 Fév 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.
Réponse acceptée
James Tursa
le 26 Fév 2018
Modifié(e) : James Tursa
le 26 Fév 2018
I can think of no reason why writing to memory from a mxArray (off of the heap) should take a significantly different amount of time than writing to memory from malloc or calloc (also off of the heap). I ran the following two sets of code on R2017a Win64 and see no significant differences:
/* double_write_test1.c */
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int x = *mxGetPr(prhs[0]);
int length = *mxGetPr(prhs[1]);
double *output_vector;
int i;
plhs[0] = mxCreateDoubleMatrix(x, 1, mxREAL);
output_vector = mxGetPr(plhs[0]);
for(i = 0; i < length; ++i) {
output_vector[i % x] += 1;
}
}
and
/* double_write_test2.c */
#include <stdlib.h> /* malloc , free */
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int x = *mxGetPr(prhs[0]);
int length = *mxGetPr(prhs[1]);
double *output_vector;
int i;
// plhs[0] = mxCreateDoubleMatrix(x, 1, mxREAL);
//double *output_vector = mxGetPr(plhs[0]);
output_vector = malloc(x*sizeof(double));
for(i = 0; i < length; ++i) {
output_vector[i % x] += 1;
}
free(output_vector);
}
The timing results:
>> tic;double_write_test1(5, 1000000000);toc
Elapsed time is 3.263384 seconds.
>> tic;double_write_test1(5, 1000000000);toc
Elapsed time is 3.004800 seconds.
>> tic;double_write_test1(5, 1000000000);toc
Elapsed time is 3.098912 seconds.
>>
>>
>> tic;double_write_test2(5, 1000000000);toc
Elapsed time is 3.071897 seconds.
>> tic;double_write_test2(5, 1000000000);toc
Elapsed time is 3.091942 seconds.
>> tic;double_write_test2(5, 1000000000);toc
Elapsed time is 3.056829 seconds.
So, timing is pretty much the same. This is all as expected on my machine. I don't know what might be happening on your machine.
I would point out that MATLAB seems to keep a store of 0'ed memory to the side for use in some circumstances. E.g., if you call mxCalloc the pointer returned may be to a memory block that has already been previously set to all 0's prior to your mxCalloc call. So you can't necessarily conclude that any timings associated with the call also included the time it took to set all of the memory to 0's since that might have been done prior to the call.
Side Note: I don't know what all "mex.h" includes, but I wouldn't necessarily trust it to include the files that have the native C function prototypes. In particular, since you are using malloc etc you should probably explicitly include a header file like stdlib.h to get the proper prototypes for the functions you are using.
8 commentaires
James Tursa
le 27 Fév 2018
Yes, Microsoft SDK. This is still strange to me, however, to have that much timing difference.
James Folberth
le 27 Fév 2018
I believe the dominant cost in the loop is the operation `i%x`. Since x isn't known at compile time, GCC-4.9 w/ -O2 wasn't able to do tricks to avoid the integer division. When the compiler optimizes out `output_vector[i%x] += 1`, the runtime drops significantly, because we no longer have to do a billion integer divisions.
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur Matrix Indexing dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!