升级 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 文件。