升级 MEX 文件以使用 64 位 API
mex 命令默认使用 -largeArrayDims 选项。本主题描述如何升级 MEX 文件以使用 64 位 API。
您可以通过调用带有 -compatibleArrayDims 选项的 mex 命令继续使用 32 位 API。有关使用此选项的详细信息,请参阅What If I Do Not Upgrade?。
要查看并更新 MEX 文件的源代码,请使用以下检查清单。
- 在编辑之前准备代码 - 请参阅备份文件并创建测试。 
- 以迭代方式更改和测试代码。 - 在使用 64 位 API 编译 MEX 文件之前,请使用更新变量重构您的现有代码。对于 Fortran,则使用Upgrade Fortran MEX Files to use 64-bit API 重构您的代码。 - 每次更改后,请编译并测试您的代码: - 使用 32 位 API 进行编译。例如,要编译 - myMexFile.c,请键入:- mex -compatibleArrayDims myMexFile.c 
- 每次重构后进行测试 - 请参阅在每个重构迭代后进行测试、调试并解决存在的差异。 
 
- 使用 64 位 API 进行编译。要编译 - myMexFile.c,请键入:- mex myMexFile.c 
- 消除故障和警告 - 请参阅解决 -largeArrayDims 编译故障和警告。 
- 比较结果 - 请参阅执行 64 位 MEX 文件并与 32 位版本的结果进行比较。 
- 检查内存 - 请参阅使用大型数组进行试验。 
以下过程使用 C/C++ 术语和示例代码。Fortran MEX 文件存在相同的问题,需要执行Upgrade Fortran MEX Files to use 64-bit API中所述的更多任务。
备份文件并创建测试
在修改代码之前,确认 MEX 文件可与 32 位 API 结合使用。至少构建预期的输入和输出列表,或创建完整的测试套件。使用这些测试,将结果与更新后的源代码进行比较。结果应该相同。
备份所有源、二进制和测试文件。
更新变量
要处理大型数组,请转换包含数组索引或大小的变量,以使用 mwSize 和 mwIndex 类型,而不是 32 位 int 类型。查看您的代码是否包含以下变量类型:
- 矩阵 API 函数直接使用的变量 - 请参阅更新用于调用 64 位 API 函数的参量。 
- 中间变量 - 请参阅更新用于数组索引和大小的变量。 
- 用作大小/索引值和用作 32 位整数的变量 - 请参阅分析其他变量。 
更新用于调用 64 位 API 函数的参量
识别代码中使用 mwSize / mwIndex 类型的 64 位 API 函数。有关函数列表,请参阅Using the 64-Bit API。搜索您用于调用函数的变量。检查函数参考文档的语法标题下面显示的函数签名。该签名确定了取 mwSize / mwIndex 值作为输入值或输出值的变量。更改您的变量以使用正确的类型。
例如,假设您的代码使用以下语句中所示的 mxCreateDoubleMatrix 函数:
int nrows,ncolumns; ... y_out = mxCreateDoubleMatrix(nrows, ncolumns, mxREAL);
要查看函数签名,请键入:
doc mxCreateDoubleMatrix
签名为:
mxArray *mxCreateDoubleMatrix(mwSize m, mwSize n, 
    mxComplexity ComplexFlag)输入参量 m 和 n 的类型为 mwSize。如表中所示更改代码。
| 替换: | 为: | 
|---|---|
| int nrows,ncolumns; | mwSize nrows,ncolumns; | 
更新用于数组索引和大小的变量
如果您的代码使用中间变量来计算大小和索引值,请将 mwSize / mwIndex 用于这些变量。例如,以下代码将 mxCreateDoubleMatrix 的输入声明为 mwSize 类型:
mwSize nrows,ncolumns; /* inputs to mxCreateDoubleMatrix */ int numDataPoints; nrows = 3; numDataPoints = nrows * 2; ncolumns = numDataPoints + 1; ... y_out = mxCreateDoubleMatrix(nrows, ncolumns, mxREAL);
该示例使用中间变量 numDataPoints(类型为 int)来计算 ncolumns 的值。如果您将 nrows 中的 64 位值复制到 32 位变量 numDataPoints,则结果值将被截断。您的 MEX 文件可能崩溃或产生错误的结果。如下表中所示,将类型 mwSize 用于 numDataPoints。
| 替换: | 为: | 
|---|---|
| int numDataPoints; | mwSize numDataPoints; | 
分析其他变量
您无需更改代码中的每个整数变量。例如,结构体和状态代码中的字段编号为 int 类型。不过,您需要识别用于多种用途的变量,必要时将其替换为多个变量。
以下示例将基于传感器的数量创建矩阵 myNumeric 和结构体 myStruct。该代码将一个变量 numSensors 同时用于数组大小和结构体中的字段数量。
mxArray *myNumeric, *myStruct; int numSensors; mwSize m, n; char **fieldnames; ... myNumeric = mxCreateDoubleMatrix(numSensors, n, mxREAL); myStruct = mxCreateStructMatrix(m, n, numSensors, fieldnames);
mxCreateDoubleMatrix 和 mxCreateStructMatrix 的函数签名为:
mxArray *mxCreateDoubleMatrix(mwSize m, mwSize n,
    mxComplexity ComplexFlag)
mxArray *mxCreateStructMatrix(mwSize m, mwSize n,
    int nfields, const char **fieldnames);
对于 mxCreateDoubleMatrix 函数,您的代码将 numSensors 用于变量 m。m 的类型为 mwSize。对于 mxCreateStructMatrix 函数,您的代码将 numSensors 用于变量 nfields。nfields 的类型为 int。要处理这两个函数,请将 numSensors 替换为两个新变量,如下表所示。
| 替换: | 为: | 
|---|---|
| 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);
 | 
在每个重构迭代后进行测试、调试并解决存在的差异
要使用 32 位 API 编译 myMexFile.c,请键入:
mex -compatibleArrayDims myMexFile.c
使用您在此过程开始时创建的测试,将更新的 MEX 文件的结果与原始二进制文件进行比较。两个 MEX 文件应返回相同的结果。否则,请调试并解决存在的任何差异。此时解决差异的难度比使用 64 位 API 编译时解决差异的难度要小。
解决 -largeArrayDims 编译故障和警告
在查看并更新代码之后,使用大型数组处理 API 来编译 MEX 文件。要使用 64 位 API 编译 myMexFile.c,请键入:
mex myMexFile.c
由于 mwSize / mwIndex 类型为 MATLAB® 类型,因此您的编译器有时将其称为 size_t、unsigned_int64 或其他类似的名称。
大多数编译问题都与 32 位和 64 位类型之间的类型不匹配有关。请参考 How do I update MEX-files to use the large array handling API (-largeArrayDims)? 中的步骤 5,了解特定编译器的常见编译问题及可能的解决方案。
执行 64 位 MEX 文件并与 32 位版本的结果进行比较
将使用 64 位 API 编译的 MEX 文件的运行结果与原始二进制文件的结果进行比较。如果存在任何差异或故障,请使用调试器调查原因。有关调试器功能的信息,请参阅您的编译器文档。
要确定在运行 MEX 文件时可能遇到的问题及可能的解决方案,请参考 How do I update MEX-files to use the large array handling API (-largeArrayDims)? 中的步骤 6。
在解决问题并升级您的 MEX 文件后,它将在使用大型数组处理 API 的同时复制原始代码的功能。
使用大型数组进行试验
如果您可以访问具有大内存量的计算机,则可以使用大型数组进行试验。一个包含 232 个元素的双精度浮点数数组(MATLAB 中的默认值)需要占用大约 32 GB 的内存。
有关演示大型数组用法的示例,请参阅Handling Large mxArrays in C MEX Files 中的 arraySize.c MEX 文件。