R2018a complex interleaved data is the new memory model
8 ビュー (過去 30 日間)
古いコメントを表示
This is a heads up for mex programmers that work with complex data. According to the Release Notes, it appears that MATLAB R2018a has undergone a major change in the way it stores complex data. It used to be separate memory blocks for the real and imag data. Now it is interleaved real & imag data elements. This brings the MATLAB complex data memory model in line with other languages and libraries built around the Fortran/C/C++ etc standards.
But it also means that all of your current mex code that works with complex data may be broken in R2018a. E.g., mxGetPr will now generate an error if the mxArray is complex and you compile with the -R2018a flag. Similar comments for the other related functions such as mxGetPi, mxGetData, mxGetImagData. If you currently use these data pointers to access complex variables inplace ... that just went out the window.
I will know more once I get R2018a, but for now I will just caution you that you may have to redo all of your mex source code to work with the new internal complex memory model. Your current code may not work at all. And the internal mxArray hacks that you have been using may not work either.
I've got a lot of FEX code that is suddenly broken in R2018a and will have to be rewritten ...
3 件のコメント
回答 (2 件)
John Aspinall
2018 年 3 月 26 日
編集済み: Steven Lord
2018 年 3 月 27 日
1. Primary memory model.
James is correct that the primary memory model for complex data is interleaved in 18a. What "primary model" means is that anywhere where arrays are running around in core MATLAB code, the core code has been built with the assumption of this memory model.
2. Compatibility of older mex files, both binary and source.
We support the compatibility of old MEX files, both old binaries, and old source rebuilt by an 18a MATLAB. But switching representations of complex data is not free. That's the "performance impact" that we're talking about here.
For a user who is passing large complex arrays across the MEX interface, they probably want to move to using the interleaved complex APIs as soon as they can. But there are many other use cases where computing on a small piece of complex data is a tiny part of the larger computation in the MEX file. In these cases, the overhead may be negligible, and those users can postpone conversion until convenient.
It's hard to talk about converting to interleaved complex without a specific use case, but we've tried to capture some common idioms here.
Bottom line is that you shouldn't have broken mex files, unless you're stepping outside the published APIs. Also, as James notes, choosing the 18a interface at the command line is an "opt-in" operation; with no choice of API specified on the command line it will default to 17b, which means you're getting the compatible option so that even if you've got your mex command stored in a makefile, it should continue to work.
3. Fortran.
We can't promise anything about future development, but let me reassure you that we hear you, and we are not abandoning Fortran.
4. MEX command line.
Finally, a word about the change in the MEX command line flags for choosing compatibility options. Walter is quite correct that we have changed from flagging by functionality affected, to flagging by release number.
We did deliberately choose control by release. We chose release numbers because of the importance of being able to build a MEX file that works in a particular MATLAB release and because the combinations of functionality were growing too large.
5. For more information.
We're planning a guest post in Steve's or Loren's blog, covering more detail about move to interleaved complex.
[SL: edited to correct one of the URLs, to hyperlink the URLs, and to fix one typo.]
8 件のコメント
Cris Luengo
2018 年 5 月 2 日
I have been waiting for this particular change for 20 years. Separate real and imaginary planes was a ridiculous idea to start with. But somehow this change is painful, needing to do major rewrites now.
Bruno Luong
2018 年 3 月 27 日
編集済み: Bruno Luong
2018 年 3 月 27 日
I have not noticed the change before reading this post, since all my MEX are still working in 2018a.
I guess there is a conversion back/and forth between interleaved (internal storage) and separate Pr/Pi pointers in compatibility mode (-R2017b). In my benchmark test of this simple MEX file, the speed is decrease by half in compatibility mode, so IMO in worth to do the conversion.
/*************************************************************************
* MATLAB MEX ROUTINE zeropad_mex.c
*
* function B = zeropad_mex(A, nhead, ntail)
* perform
* >> B = cat(1, zeros(nhead,1), A(:), zeros(ntail,1));
*
* A must be array double, real or complex
*
* >> mex -O -R2018a zeropad_mex.c
* For compatibility:
* >> mex -O -R2017b zeropad_mex.c
*
* Author: Bruno Luong <b.luong@fogale.com>
* History
* Original: 16/Mars/2018
************************************************************************/
#include "mex.h"
#include "matrix.h"
#include "math.h"
#include <string.h>
#define A_IN prhs[0]
#define NHEAD_IN prhs[1]
#define NTAIL_IN prhs[2]
#define B_OUT plhs[0]
#define CHECK_ARG 0
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
size_t m, nhead, ntail;
#if MX_HAS_INTERLEAVED_COMPLEX
mxComplexDouble *Ac, *Bc;
#endif
double *Ar, *Ai, *Br, *Bi;
mxComplexity mC;
#if (CHECK_ARG == 1)
if (nrhs != 3)
mexErrMsgTxt("zeropad_mex requires 2 inputs");
if (mxGetClassID(A_IN) != mxDOUBLE_CLASS)
mexErrMsgTxt("zeropad_mex A must be double");
#endif
nhead = (size_t)mxGetScalar(NHEAD_IN);
ntail = (size_t)mxGetScalar(NTAIL_IN);
#if MX_HAS_INTERLEAVED_COMPLEX
if (mxIsComplex(A_IN))
{
Ac = mxGetComplexDoubles(A_IN);
mC = mxCOMPLEX;
}
else
{
Ar = mxGetDoubles(A_IN);
mC = mxREAL;
}
Ai = NULL;
#else
Ar = mxGetPr(A_IN);
Ai = mxGetPi(A_IN);
if (Ai == NULL)
mC = mxREAL;
else
mC = mxCOMPLEX;
#endif
m = mxGetNumberOfElements(A_IN);
B_OUT = mxCreateNumericMatrix(m+nhead+ntail, 1, mxDOUBLE_CLASS, mC);
#if MX_HAS_INTERLEAVED_COMPLEX
if (mxIsComplex(B_OUT))
{
Bc = mxGetComplexDoubles(B_OUT);
memcpy(Bc+nhead,Ac,sizeof(mxComplexDouble)*m);
}
else
{
Br = mxGetDoubles(B_OUT);
memcpy(Br+nhead,Ar,sizeof(double)*m);
}
#else
Br = mxGetPr(B_OUT);
Bi = mxGetPi(B_OUT);
memcpy(Br+nhead,Ar,sizeof(double)*m);
if (Ai != NULL) memcpy(Bi+nhead,Ai,sizeof(double)*m);
#endif
} /* mexFunction */
0 件のコメント
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!