|
Peter Boettcher <boettcher@ll.mit.edu> wrote in message <muy4ox9ae1p.fsf@G99-Boettcher.llan.ll.mit.edu>...
> >
> > Related open question for the group: Anybody know how to make a lazy
> > copy of a variable inside a mex routine? This would be a classic
> > example of where a mex version of typecast could be made more
> > efficient than the MATLAB intrinsic typecast, except that I cannot
> > figure out how to do it.
>
> Try
>
> mxCreateSharedCopy()
> mxCreateSharedDataCopy()
>
> Completely untested.
>
> -Peter
Brilliant! It was *almost* exactly what I was looking for. I combined the struct mxArray_tag stuff you put together and listed on a website with the mxCreateSharedDataCopy() function you mentioned above and created a shared data copy. Then I manually changed the class_id of the variable and set the dimensions. I ended up with a typecast version of the variable that shares the data. Looks like it works (at least no seg faults so far ...)
James Tursa
e.g., the following (unpolished) code takes a double array input and creates a shared typecast int32 version of it (by doubling the number of rows). I did it for a large 100MB+ array and it worked. Used feature memstats to verify that clearing the original did not free up the memory, but clearing the typecast copy did free up the memory.
----------------------------------------------------------------------------------------------
#include "mex.h"
/* Definition of structure mxArray_tag for debugging purposes. Might not
* be fully correct for Matlab 2006b or 2007a, but the important things
* are. Thanks to Peter Boettcher.
*/
struct mxArray_tag {
const char *name;
mxClassID class_id;
int vartype;
mxArray *crosslink;
int number_of_dims;
int refcount;
struct {
unsigned int scalar_flag : 1;
unsigned int flag1 : 1;
unsigned int flag2 : 1;
unsigned int flag3 : 1;
unsigned int flag4 : 1;
unsigned int flag5 : 1;
unsigned int flag6 : 1;
unsigned int flag7 : 1;
unsigned int private_data_flag : 1;
unsigned int flag8 : 1;
unsigned int flag9 : 1;
unsigned int flag10 : 1;
unsigned int flag11 : 4;
unsigned int flag12 : 8;
unsigned int flag13 : 8;
} flags;
int rowdim;
int coldim;
union {
struct {
double *pdata; // original: void*
double *pimag_data; // original: void*
void *irptr;
void *jcptr;
int nelements;
int nfields;
} number_array;
struct {
mxArray **pdata;
char *field_names;
void *dummy1;
void *dummy2;
int dummy3;
int nfields;
} struct_array;
struct {
void *pdata; /*mxGetInfo*/
char *field_names;
char *name;
int checksum;
int nelements;
int reserved;
} object_array;
} data;
};
mxArray *mxCreateSharedDataCopy(const mxArray *mx);
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if( nrhs != 1 || nlhs > 1 ) {
mexErrMsgTxt("Expect exactly 1 input and 0 or 1 output.");
}
if( !mxIsDouble(prhs[0]) || mxIsSparse(prhs[0]) ) {
mexErrMsgTxt("Input must be full double matrix.");
}
plhs[0] = mxCreateSharedDataCopy(prhs[0]);
(plhs[0])->class_id = mxINT32_CLASS;
mxSetM(plhs[0],mxGetM(plhs[0])*2);
}
|