Upgrade MEX Files to Use 64-Bit API
The mex
command uses the -largeArrayDims
option by default. This topic describes how to upgrade your MEX files to use the 64-bit
API.
You can continue to use the 32-bit API by calling the mex
command
with the -compatibleArrayDims
option. However, for more information
about using this option, see What If I Do Not Upgrade?.
To review and update MEX file source code, use the following checklist.
Prepare your code before editing — see Back Up Files and Create Tests.
Iteratively change and test code.
Before building your MEX files with the 64-bit API, refactor your existing code using Update Variables and, for Fortran, Upgrade Fortran MEX Files to use 64-bit API.
After each change, build and test your code:
Build with the 32-bit API. For example, to build
myMexFile.c
, type:mex -compatibleArrayDims myMexFile.c
Test after each refactoring — see Test, Debug, and Resolve Differences After Each Refactoring Iteration.
Compile using the 64-bit API. To build
myMexFile.c
, type:mex myMexFile.c
Resolve failures and warnings — see Resolve -largeArrayDims Build Failures and Warnings.
Compare Results — see Execute 64-Bit MEX File and Compare Results with 32-Bit Version.
Check memory — see Experiment with Large Arrays.
The following procedures use C/C++ terminology and example code. Fortran MEX files share issues, with more tasks described in Upgrade Fortran MEX Files to use 64-bit API.
Back Up Files and Create Tests
Before modifying your code, verify that the MEX file works with the 32-bit API. At a minimum, build a list of expected inputs and outputs, or create a full test suite. Use these tests to compare the results with the updated source code. The results should be identical.
Back up all source, binary, and test files.
Update Variables
To handle large arrays, convert variables containing array indices or sizes to use
the mwSize
and mwIndex
types instead of
the 32-bit int
type. Review your code to see if it contains the
following types of variables:
Variables used directly by the Matrix API functions — see Update Arguments Used to Call Functions in the 64-Bit API.
Intermediate variables — see Update Variables Used for Array Indices and Sizes.
Variables used as both size/index values and as 32-bit integers — see Analyze Other Variables.
Update Arguments Used to Call Functions in the 64-Bit API
Identify the 64-bit API functions in your code that use the
mwSize
/ mwIndex
types. For the list of
functions, see Using the 64-Bit API. Search for the variables
that you use to call the functions. Check the function signature, shown under the
Syntax heading on the function reference
documentation. The signature identifies the variables that take
mwSize
/ mwIndex
values as input or output
values. Change your variables to use the correct type.
For example, suppose that your code uses the
mxCreateDoubleMatrix
function, as shown in the following
statements:
int nrows,ncolumns; ... y_out = mxCreateDoubleMatrix(nrows, ncolumns, mxREAL);
To see the function signature, type:
doc mxCreateDoubleMatrix
The signature is:
mxArray *mxCreateDoubleMatrix(mwSize m, mwSize n, mxComplexity ComplexFlag)
The type for input arguments m
and n
is
mwSize
. Change your code as shown in the table.
Replace: | With: |
---|---|
int nrows,ncolumns; |
mwSize nrows,ncolumns; |
Update Variables Used for Array Indices and Sizes
If your code uses intermediate variables to calculate size and index values, use
mwSize
/ mwIndex
for these variables. For
example, the following code declares the inputs to
mxCreateDoubleMatrix
as type
mwSize
:
mwSize nrows,ncolumns; /* inputs to mxCreateDoubleMatrix */ int numDataPoints; nrows = 3; numDataPoints = nrows * 2; ncolumns = numDataPoints + 1; ... y_out = mxCreateDoubleMatrix(nrows, ncolumns, mxREAL);
This example uses the intermediate variable, numDataPoints (of
type int
), to calculate the value of ncolumns.
If you copy a 64-bit value from nrows into the 32-bit variable,
numDataPoints, the resulting value truncates. Your MEX file
could crash or produce incorrect results. Use type mwSize
for
numDataPoints, as shown in the following table.
Replace: | With: |
---|---|
int numDataPoints; |
mwSize numDataPoints; |
Analyze Other Variables
You do not need to change every integer variable in your code. For example, field
numbers in structures and status codes are of type int
. However,
you need to identify variables used for multiple purposes and, if necessary, replace
them with multiple variables.
The following example creates a matrix, myNumeric, and a structure, myStruct, based on the number of sensors. The code uses one variable, numSensors, for both the size of the array and the number of fields in the structure.
mxArray *myNumeric, *myStruct; int numSensors; mwSize m, n; char **fieldnames; ... myNumeric = mxCreateDoubleMatrix(numSensors, n, mxREAL); myStruct = mxCreateStructMatrix(m, n, numSensors, fieldnames);
The function signatures for mxCreateDoubleMatrix
and
mxCreateStructMatrix
are:
mxArray *mxCreateDoubleMatrix(mwSize m, mwSize n, mxComplexity ComplexFlag) mxArray *mxCreateStructMatrix(mwSize m, mwSize n, int nfields, const char **fieldnames);
For the mxCreateDoubleMatrix
function, your code uses
numSensors for the variable m. The type
for m is mwSize
. For the
mxCreateStructMatrix
function, your code uses
numSensors for the variable nfields. The
type for nfields is int
. To handle both
functions, replace numSensors with two new variables, as shown in
the following table.
Replace: | With: |
---|---|
int numSensors; |
/* create 2 variables */ /* of different types */ mwSize numSensorSize; int numSensorFields; |
myNumeric = mxCreateDoubleMatrix( numSensors, n, mxREAL); |
/* use mwSize variable */ /* numSensorSize */ myNumeric = mxCreateDoubleMatrix( numSensorSize, n, mxREAL); |
myStruct = mxCreateStructMatrix( m, n, numSensors, fieldnames); |
/* use int variable */ /* numSensorFields */ myStruct = mxCreateStructMatrix( m, n, numSensorFields, fieldnames); |
Test, Debug, and Resolve Differences After Each Refactoring Iteration
To build myMexFile.c
with the 32-bit API, type:
mex -compatibleArrayDims myMexFile.c
Use the tests you created at the beginning of this process to compare the results of your updated MEX file with your original binary file. Both MEX files should return identical results. If not, debug and resolve any differences. Differences are easier to resolve now than when you build using the 64-bit API.
Resolve -largeArrayDims
Build Failures and Warnings
After reviewing and updating your code, compile your MEX file using the large
array handling API. To build myMexFile.c
with the 64-bit API,
type:
mex myMexFile.c
Since the mwSize
/ mwIndex
types are
MATLAB® types, your compiler sometimes refers to them as
size_t
, unsigned_int64
, or by other
similar names.
Most build problems are related to type mismatches between 32-bit and 64-bit types. Refer to Step 5 in How do I update MEX-files to use the large array handling API (-largeArrayDims)? to identify common build problems for specific compilers, and possible solutions.
Execute 64-Bit MEX File and Compare Results with 32-Bit Version
Compare the results of running your MEX file compiled with the 64-bit API with the results from your original binary. If there are any differences or failures, use a debugger to investigate the cause. For information on the capabilities of your debugger, refer to your compiler documentation.
To identify issues—and possible solutions—you might encounter when running your MEX files, refer to Step 6 in How do I update MEX-files to use the large array handling API (-largeArrayDims)?.
After you resolve issues and upgrade your MEX file, it replicates the functionality of your original code while using the large array handling API.
Experiment with Large Arrays
If you have access to a machine with large amounts of memory, you can experiment with large arrays. An array of double-precision floating-point numbers (the default in MATLAB) with 232 elements takes approximately 32 GB of memory.
For an example that demonstrates the use of large arrays, see the
arraySize.c
MEX file in Handling Large mxArrays in C MEX Files.