MEX中的单元阵列输出为慢速

时间:2015-10-07 19:28:59

标签: c++ performance matlab mex

我观察到以下与单元阵列有关的奇怪问题。我目前正在使用Matlab R2013a。请考虑以下代码。

#include <iostream>
#include <vector>
#include <chrono>

#include <mex.h>
#undef printf       // to undo redefinition of printf by mex.h
#include <matrix.h>

void mexFunction(int nlhs, mxArray **plhs, int nrhs, mxArray **prhs) {

    if (nrhs != 0) {
        mexErrMsgIdAndTxt("CellArray:InvalidInput", "There are too many input arguments required no of input args = 0");
    }
    if (nlhs != 1) {
        mexErrMsgIdAndTxt("CellArray:InvalidOutput", "Incorrect number of output arguments required no of output args = 1");
    }

    int CellArrSize = 50820;   // Number is prime
    int CellContentSizeCurr = 1;
    int CurrentCell = 732;

    mwSize CellArrayDims[] = { CellArrSize, 1 };
    std::vector<int *> IntArrayofArrays(CellArrSize, nullptr);
    std::vector<int> CellContentSize(CellArrSize);

    plhs[0] = mxCreateCellArray(2, CellArrayDims);

    // Filling the Array of Arrays with the content to output
    // into the cell array
    for (int i = 0; i < CellArrSize; ++i) {
        CellContentSizeCurr = (CellContentSizeCurr * 398) % 431; // 431 is primes 
        #ifdef IS_CONTIG
            CurrentCell = i;
        #else
            CurrentCell = ((CurrentCell + 1) * 732) % 50821 - 1;
        #endif
        IntArrayofArrays[CurrentCell] = reinterpret_cast<int *>(mxCalloc(CellContentSizeCurr, sizeof(int)));
        for (int j = 0; j < CellContentSizeCurr; ++j) {
            IntArrayofArrays[CurrentCell][j] = i * CellContentSizeCurr + j;
        }
        CellContentSize[CurrentCell] = CellContentSizeCurr;
    }

    // Performing output of the Array of Array into Cell array
    // (along with profiling code)
    int TimeTakeninus = 0;
    for (int i = 0; i < CellArrSize; ++i) {
        mxArray * tempmxArray;
        mwSize mxArrayDims[] = { 0,0 };
        tempmxArray = mxCreateNumericArray(2, mxArrayDims, mxINT32_CLASS, mxREAL);
        mxSetM(tempmxArray, CellContentSize[i]);
        mxSetN(tempmxArray, 1);

        auto TimeBeg = std::chrono::system_clock::now();
        mxSetData(tempmxArray, IntArrayofArrays[i]);
        auto TimeEnd = std::chrono::system_clock::now();
        TimeTakeninus += std::chrono::duration_cast<std::chrono::microseconds>(TimeEnd - TimeBeg).count();
        mxSetCell(plhs[0], i, tempmxArray);
    }

    mexPrintf("The time taken to perform output = %d ms\n", TimeTakeninus / 1000);
    mexEvalString("drawnow");
}

有一个选项(define)IS_CONTIG,它基本上决定了连续数组中的内存 IntArrayofArrays`是否连续分配。选择上面的数字即使在 在不连续的情况下,从0到大小为1的所有单元格索引都被填充(并分配)了一次。

MATLAB方面很简单

FinalCellArray = MexCellArrayTest();

观察到的问题如下

  • 如果我们删除了IS_CONTIG的定义并允许连续分配内存, 执行快速结束(输出<1ms)。
  • 但是,在另一种情况下,使用非连续的输出部分(由...检测到) 分析代码)需要将近6秒钟。
  • 请注意,输出是使用mxSetData函数给出的(原则上) 只复制IntArrayofArrays [i]传递给它的内存位置的地址。

    为什么会有很大差异?

0 个答案:

没有答案