From: Wes on
Hello all,

System info:
Ubuntu Linux, kernel version: 2.6.28-18-generic
MATLAB 7.6.0.324 (R2008a)

I am using the C API to access the MATLAB engine from a C program.

I have an existing block of data which I'd like to operate on with the MATLAB engine. I've managed to do this by creating a mxArray via mxCreateDoubleMatrix(), then copying the data from shared memory into the newly created matrix's data segment. I can perform MATALB operations on it using engPutVariable() and engEvalString() quite nicely, and retrieve the results as desired. However, since my data are substantially large with respect to the available RAM in my system, I'd prefer to be able to simply point the data segment in my mxArray struct to the data which already exists. This can be done (with success) via mxSetPr(), but the initial mxCreateDoubleMatrix() invocation still allocates memory for the data, which I do not require.

My question: Is there a way to create a matrix suitable for the MATLAB engine to operate on which does not allocate memory for the data it will hold, but simply uses an existing pointer?

I looked at the mxArray_tag (mxArray) struct in matrix.h, but I've no idea what I'd fill most of the parameters with...

Any help will be appreciated!
From: James Tursa on
"Wes " <dont.spam(a)me.pls> wrote in message <hpfsuu$sv7$1(a)fred.mathworks.com>...
> Hello all,
>
> System info:
> Ubuntu Linux, kernel version: 2.6.28-18-generic
> MATLAB 7.6.0.324 (R2008a)
>
> I am using the C API to access the MATLAB engine from a C program.
>
> I have an existing block of data which I'd like to operate on with the MATLAB engine. I've managed to do this by creating a mxArray via mxCreateDoubleMatrix(), then copying the data from shared memory into the newly created matrix's data segment. I can perform MATALB operations on it using engPutVariable() and engEvalString() quite nicely, and retrieve the results as desired. However, since my data are substantially large with respect to the available RAM in my system, I'd prefer to be able to simply point the data segment in my mxArray struct to the data which already exists. This can be done (with success) via mxSetPr(), but the initial mxCreateDoubleMatrix() invocation still allocates memory for the data, which I do not require.
>
> My question: Is there a way to create a matrix suitable for the MATLAB engine to operate on which does not allocate memory for the data it will hold, but simply uses an existing pointer?
>
> I looked at the mxArray_tag (mxArray) struct in matrix.h, but I've no idea what I'd fill most of the parameters with...
>
> Any help will be appreciated!

You can create a 0x0 matrix and then use mxSetM, mxSetN, and mxSetPr to do this. e.g.,

double *pr = your shared data;
mxArray *mx;
mx = mxCreateDoubleMatrix(0, 0, mxREAL);
mxSetPr(mx,pr);
mxSetM(mx,m);
mxSetN(mx,n);
engPutVariable( etc. )
mxSetpr(mx,NULL); <-- be sure to do this !!!
mxDestroyArray(mx); <-- before you do this !!!
engEvalString( etc. )
engGetVariable( etc. )

Generally, however, you cannot avoid extra copies when working with the MATLAB engine. You have to make a copy for the engine itself. Then you have to operate on it in the engine. Then you have to get a copy back from the engine. Then you have to copy that into your shared memory. etc. etc. To cut down on this you can do what I suggest above. Also, you can use engEvalString( ) with a clear command on the engine side to free large variables in the engine as soon as you are done with them. If you are desperate you could write a mex routine that the engine calls and have that mex routine access the shared memory directly.

James Tursa
From: Wes on
"James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <hpfu31$gqn$1(a)fred.mathworks.com>...
> "Wes " <dont.spam(a)me.pls> wrote in message <hpfsuu$sv7$1(a)fred.mathworks.com>...
> > Hello all,
> >
> > System info:
> > Ubuntu Linux, kernel version: 2.6.28-18-generic
> > MATLAB 7.6.0.324 (R2008a)
> >
> > I am using the C API to access the MATLAB engine from a C program.
> >
> > I have an existing block of data which I'd like to operate on with the MATLAB engine. I've managed to do this by creating a mxArray via mxCreateDoubleMatrix(), then copying the data from shared memory into the newly created matrix's data segment. I can perform MATALB operations on it using engPutVariable() and engEvalString() quite nicely, and retrieve the results as desired. However, since my data are substantially large with respect to the available RAM in my system, I'd prefer to be able to simply point the data segment in my mxArray struct to the data which already exists. This can be done (with success) via mxSetPr(), but the initial mxCreateDoubleMatrix() invocation still allocates memory for the data, which I do not require.
> >
> > My question: Is there a way to create a matrix suitable for the MATLAB engine to operate on which does not allocate memory for the data it will hold, but simply uses an existing pointer?
> >
> > I looked at the mxArray_tag (mxArray) struct in matrix.h, but I've no idea what I'd fill most of the parameters with...
> >
> > Any help will be appreciated!
>
> You can create a 0x0 matrix and then use mxSetM, mxSetN, and mxSetPr to do this. e.g.,
>
> double *pr = your shared data;
> mxArray *mx;
> mx = mxCreateDoubleMatrix(0, 0, mxREAL);
> mxSetPr(mx,pr);
> mxSetM(mx,m);
> mxSetN(mx,n);
> engPutVariable( etc. )
> mxSetpr(mx,NULL); <-- be sure to do this !!!
> mxDestroyArray(mx); <-- before you do this !!!
> engEvalString( etc. )
> engGetVariable( etc. )
>
> Generally, however, you cannot avoid extra copies when working with the MATLAB engine. You have to make a copy for the engine itself. Then you have to operate on it in the engine. Then you have to get a copy back from the engine. Then you have to copy that into your shared memory. etc. etc. To cut down on this you can do what I suggest above. Also, you can use engEvalString( ) with a clear command on the engine side to free large variables in the engine as soon as you are done with them. If you are desperate you could write a mex routine that the engine calls and have that mex routine access the shared memory directly.
>
> James Tursa

Great! Thanks for the info.

So the engPutVariable() routine makes a copy of the data for the MATLAB engine? I'm guessing the engine is executed as a separate process and passed the data to work on (thus incurring additional RAM usage) via some sort of IPC. Correct?

I'll look into a mex routine to attach the shared memory segment then. Thanks again for your help.

Cheers,

Wes
From: James Tursa on
"Wes " <dont.spam(a)me.pls> wrote in message <hpfvui$g0p$1(a)fred.mathworks.com>...
>
> Great! Thanks for the info.
>
> So the engPutVariable() routine makes a copy of the data for the MATLAB engine? I'm guessing the engine is executed as a separate process and passed the data to work on (thus incurring additional RAM usage) via some sort of IPC. Correct?

Yes, the engPutVariable routine makes a copy of the data for the MATLAB engine. On a PC the engine is run through a COM server. Using a mex routine directly you can often avoid this extra copy through the use of the mexCallMATLAB routine.

James Tursa