contiguous memory for complex arrays in mex

4 views (last 30 days)
Is it possible to allocate a complex array in a mex file and have the real and imaginary parts be contiguous with each other? I'm working with very large matrices and need to conserve memory and would like to not have to make a copy of the input matrices to get them into FORTRAN format. If the memory were contiguous, I could just rearrange the data into interleaved real and imaginary. I've already been able to pass in a real valued array from matlab and have LAPACK treat it as a complex (it just assumes the real and imaginary are interleaved), but this isn't exactly an elegant solution since I still have to write the data to a file and read it back into complex form. At that point it becomes useless to use MATLAB at all and I might as well just write a standalone program in C or FORTRAN. Any ideas if this can be done or am I out of luck?

Accepted Answer

James Tursa
James Tursa on 13 Dec 2011
Yes and No. It is easily possible to physically do this, but the clearing of such a variable will likely crash MATLAB if you are not very careful. The outline is as follows.
In the mex routine create a double array that is sized to hold all of your intended complex data. E.g., if you want a 1x5 complex array then create a double array that is 1x10. Then manually use mxSetN to change the column size to 5. Then pick the midpoint of the real data area and use mxSetPi to set the imaginary data pointer to that address. That will create a complex mxArray variable with the real and imaginary parts contiguous.
This will work fine up until the point that MATLAB tries to clear this variable from memory. Then it will try to free the address you just set with the mxSetPi function. Since this is not a valid address to free, the results are unpredictable and MATLAB will likely crash.
The only robust solution I can think of is to manually create a shared data copy of this variable, make it persistent, and keep this shared data copy inside the mex routine so MATLAB cannot try to clear it. Then use a mexAtExit function to manually reverse the process, use mxSetPi with a NULL, and then clear the variable. But I will tell you right now that this is very tricky to accomplish and requires that you dig under the hood of the mxArray structure to do some unofficial manipulation. You need to be able to detect when the mxArray is shared with other variables inside your mex routine, etc etc. Not recommended for the faint of heart and not easy to accomplish even for a seasoned programmer IMO.
You might be able to get away with it if you can keep all the operations inside the mex routine so that you can carefully manage all of the operations on the variable to ensure there is no shared data copy of it floating around in memory elsewhere, and then manually fix & clear it yourself inside the mex routine.
What operations will you be doing with this variable?
  5 Comments
James Tursa
James Tursa on 14 Dec 2011
P.P.S. This problem intrigued me so I went ahead and coded it up. I will write up some documentation and post it to the FEX in the next day or two. My routine will basically turn any numeric real variable (with an even number of elements) into a "contiguous" complex variable in-place, or vice-versa. Keeps a shared data copy of it off to the side so that MATLAB will not attempt to clear it. The routine will clean up everything once the user is done with the variables.
Sean Little
Sean Little on 21 Nov 2012
James, did you ever post that code? It sounds like exactly what I need, but I don't see it on the file exchange.

Sign in to comment.

More Answers (1)

the cyclist
the cyclist on 13 Dec 2011
This page has info that looks like it might be helpful for what you are trying to do:
http://www.mathworks.com/help/techdoc/matlab_external/br_2m24-1.html#f32627
In particular, it mentions the fort2mat() and mat2fort() functions.
  1 Comment
Steve
Steve on 13 Dec 2011
Thanks cyclist. I've used those functions before, but they have the problem of having to create a copy of the data before they can be used. If I wanted to do an inversion, I'd have to create a copy of the input array using mat2fort, use lapack to invert it, and create another copy using fort2mat to return the answer. I'd need 3x the memory I would if I could just force the pointer to the imaginary part of the matrix to come immediately after the real part and do the inversion in place.

Sign in to comment.

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) 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!