R2018a complex interleaved data is the new memory model

8 ビュー (過去 30 日間)
James Tursa
James Tursa 2018 年 3 月 22 日
コメント済み: James Tursa 2020 年 7 月 8 日
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 件のコメント
James Tursa
James Tursa 2018 年 3 月 22 日
編集済み: James Tursa 2018 年 3 月 23 日
To my reading of the Release Notes, the memory model of the underlying mxArray in R2018a is fixed ... it is the interleaved complex data model. That cannot be changed and there is no other memory model available. That being said, it is unclear if the old separate complex memory model is actually supported within MATLAB, or if such variables used in mex routines are simply converted to/from the interleaved model on entry/exit from the mex routine (i.e. copy-in/copy-out), or maybe something else.
The -R2017b compile flag you are referring to appears to me to simply cause linking to a library that provides an interface for the old function signatures (mxGetPr etc) into the new memory model. But the functionality of these functions has changed as noted above and more detailed in the Release Notes. The only way mxGetPr could work with a complex variable in R2018a is if a copy of the real data were made and a pointer to that copy were returned by mxGetPr. I don't see any other way it could work. If the -R2018a compile flag were used, using mxGetPr on a complex variable generates an error.
The Release Notes don't have a lot of information on this, and in some cases are contradictory, so I am guessing a bit on this. E.g., when I see the phrase "... you might notice a performance impact as MATLAB accesses the compatibility interface ..." I jump to the conclusion that there is data copying going on in the background when using the old mxGetPr and friends with complex variables.
I'll update my findings once I get a copy of R2018a to test with ...
James Tursa
James Tursa 2018 年 3 月 23 日
編集済み: James Tursa 2018 年 3 月 23 日
It is also unclear what this Release Note means:
"... MATLAB does not support the interleaved complex API for Fortran functions ..."
Will all future Fortran complex mxArray data access be forced to be data copies unless a hack is used?

サインインしてコメントする。

回答 (2 件)

John Aspinall
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
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.
James Tursa
James Tursa 2020 年 7 月 8 日
FYI,
See this FEX submission for reading and writing interleaved complex data in R2018a or later without extra data copies:
See this FEX submission for reinterpreting an existing real variable as interleaved complex or vice-versa in R2018a or later:

サインインしてコメントする。


Bruno Luong
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 */

カテゴリ

Help Center および File ExchangeWrite C Functions Callable from MATLAB (MEX Files) についてさらに検索

タグ

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by