Mex 文件和内存管理

Mex files and memory management

我有一个 mex 代码,其中输出变量与输入变量同名,但它的大小因 mex 代码的操作而改变。例如,我有这样的东西:

A=Function(A) 其中输入中的 A 是 100 X 1 向量(在我的模拟中大得多),输出 A 是 50 X 1 向量。我想了解在这种情况下如何管理内存。运算完成后,A现在是否占用了50 X 1的space,剩下的可以自由分配给其他变量?

谢谢!

悉达多

这是正确的,原始 A 的数据缓冲区被 MATLAB 销毁并创建了一个新缓冲区(相同的 mxArray 结构地址可能通过将新地址复制到释放原始数组的数据缓冲区后的原始数据)。 这是假设您不是在您的 MEX 文件中写入 prhs[i]

你可以用 format debug 看到这个。您会观察到输出 mxArray 具有相同的地址,但它的数据缓冲区具有不同的地址,因此它显然重新分配了输出数组。这表明原始缓冲区已被释放或排队等待释放。

从文件 testMEX.mexw64 的更改输出开始,它获取输入数组第一行的前半部分并将其复制到新数组中:

>> format debug
>> A = rand(1,8)
A =

Structure address = efbb890
m = 1
n = 8
pr = 77bb6c40
pi = 0
    0.2581    0.4087    0.5949    0.2622    0.6028    0.7112    0.2217    0.1174
>> A = testMEX(A)
A =

Structure address = efbb890
m = 1
n = 4
pr = 77c80380
pi = 0
    0.2581    0.4087    0.5949    0.2622

请注意 pr 不同 ,这意味着 MATLAB 已经创建了一个新的数据缓冲区。但是,mxArray "Structure address" 是一样的。因此,至少,旧数据缓冲区将被释放。原来的 mxArray 结构是简单地变异还是创建了一个新的 mxArray 是另一个问题(见下文)。


编辑: 以下是一些证据表明创建了一个全新的 mxArray 并将其复制到旧的 mxArray

将以下两行添加到 MEX 函数中:

mexPrintf("prhs[0] = %X, mxGetPr = %X, value = %lf\n", 
    prhs[0], mxGetPr(prhs[0]), *mxGetPr(prhs[0]));
mexPrintf("plhs[0] = %X, mxGetPr = %X, value = %lf\n", 
    plhs[0], mxGetPr(plhs[0]), *mxGetPr(plhs[0]));

结果是:

prhs[0] = EFBB890, mxGetPr = 6546D840, value = 0.258065
plhs[0] = EFA2DA0, mxGetPr = 77B65660, value = 0.258065

显然在包含输出 (plhs[0]) 的 EFA2DA0 中有 临时 mxArray,而这个 mxArray header/structure完全复制到旧的 mxArray 结构(基础 MATLAB 工作区中的 A 结构)。在此复制发生之前,MATLAB 肯定会在 6546D840.

处释放数据缓冲区

testMEX.cpp

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[],  int nrhs, const mxArray *prhs[])
{
    mxAssert(nrhs == 1 && mxGetM(prhs[0]) == 1, "Input must be a row vector.");
    double *A = mxGetPr(prhs[0]);
    size_t cols = mxGetN(prhs[0]);
    size_t newCols = cols / 2;

    plhs[0] = mxCreateDoubleMatrix(1, newCols, mxREAL);

    for (int i = 0; i < newCols; ++i)
        mxGetPr(plhs[0])[i] = A[i];

    mexPrintf("prhs[0] = %X, mxGetPr = %X, value = %lf\n", 
        prhs[0], mxGetPr(prhs[0]), *mxGetPr(prhs[0]));
    mexPrintf("plhs[0] = %X, mxGetPr = %X, value = %lf\n", 
        plhs[0], mxGetPr(plhs[0]), *mxGetPr(plhs[0]));

}