C++ C+中的MATLAB张量索引+;

C++ C+中的MATLAB张量索引+;,c++,matlab,segmentation-fault,mex,C++,Matlab,Segmentation Fault,Mex,我尝试加载包含C++中已知维度张量的.Mat文件;代码>144x192x256 我已经将读取操作的线性索引调整为MATLAB中的column major。但是,我仍然遇到内存访问问题 void FeatureLoader::readMat(const std::string &fname, Image< std::vector<float> > *out) { //Read MAT file. const char mode = 'r';

我尝试加载包含C++中已知维度张量的.Mat文件;代码>144x192x256

我已经将读取操作的线性索引调整为MATLAB中的column major。但是,我仍然遇到内存访问问题

void FeatureLoader::readMat(const std::string &fname, Image< std::vector<float> > *out) {
    //Read MAT file.
    const char mode = 'r';
    MATFile *matFile = matOpen(fname.c_str(), &mode);
    if (matFile == NULL) {
        throw std::runtime_error("Cannot read MAT file.");
    }


    //Copy the data from column major to row major storage.
    float *newData = newImage->GetData();
    const mxArray *arr = matGetVariable(matFile, "map");
    if (arr == NULL) {
        throw std::runtime_error("Cannot read variable.");
    }

    double *arrData = (double*)mxGetPr(arr);
#pragma omp parallel for
    for (int i = 0; i < 144; i++) {
#pragma omp parallel for
        for (int j = 0; j < 192; j++) {
            for (int k = 0; k < 256; k++) {
                int rowMajIdx = (i * 192 + j) * 256 + k;
                int colMajIdx = (j * 144 + i) * 256 + k;
                newData[rowMajIdx] = static_cast<float>(arrData[colMajIdx]);
            }
        }
    }
}

这是MATLAB使用的基本表示法吗?

行mayor和列mayor
Idx的索引中存在一些错误。此外,由于随机内存访问(内存延迟是关键!),天真地访问数据可能会导致非常慢的时间

< >从MATLAB到C++类型(从3D到1D)的最好方法是下面的例子。

在本例中,我们演示了如何从MATLAB获取双实型3D矩阵,并将其传递给C
double*
数组

本示例的主要目的是展示如何从MATLAB MEX阵列获取数据,并强调矩阵存储和处理中的一些小细节

matrixIn.cpp
#包括“mex.h”
void MEX函数(整数nlhs,mxArray*plhs[],
整数nrhs,mxArray const*prhs[]{
//检查输入量
如果(nrhs!=1){
MEXERMSGIDANDTXT(“matrixIn:InvalidInput”,“MEX文件的输入数无效”);
}
//检查输入类型
如果(!mxisDuble(prhs[0])| | mxIsComplex(prhs[0])){
MEXERMSGIDANDTXT(“matrixIn:InvalidType”,“输入矩阵必须是双精度非复杂数组”);
}
//提取数据
double const*const matrixAux=静态_cast(mxGetData(prhs[0]);
//获取矩阵大小
常量mwSize*sizeInputMatrix=mxGetDimensions(prhs[0]);
//在C中分配数组。注意:它是1D数组,而不是3D数组,即使我们的输入是3D
double*matrixInC=(double*)malloc(sizeInputMatrix[0]*sizeInputMatrix[1]*sizeInputMatrix[2]*sizeof(double));
//MATLAB是列主键,而不是行主键(如C)。我们需要对数字重新排序
//基本置换维数
//注意:循环的顺序经过优化,可实现最快的内存访问!
//这将使速度提高约300%
const int size0=sizeInputMatrix[0];//const使编译器优化生效
常量int size1=sizeInputMatrix[1];
const int size2=sizeInputMatrix[2];
对于(int j=0;j

应注意的相关概念:

  • MATLAB矩阵在内存中都是一维的,无论它们在MATLAB中使用时有多少维。对于C/C++库中的大多数(如果不是全部的话)主矩阵表示也是如此,因为它允许优化和更快的执行

  • 您需要在循环中将矩阵从MATLAB显式复制到C

  • MATLAB矩阵是按列主顺序存储的,就像Fortran一样,但C/C++和大多数现代语言是按行主顺序存储的。排列输入矩阵很重要,否则数据看起来会完全不同

本例中的相关功能包括:

  • mxidouble
    检查输入是否为
    double
    类型
  • mxicomplex
    检查输入是实输入还是虚输入
  • mxGetData
    返回指向输入数组中真实数据的指针<代码>空值
如果没有实际数据
  • mxGetDimensions
    返回指向
    mwSize
    数组的指针,每个索引中都有维度的大小

  • 没有C/C++这样的东西-它们是两种独立的语言,应该可以通过这种方式访问数据。但是您应该检查数组的类型
    arr
    。它可能不是双倍的,那么你的读数就超出了范围。当然,你也应该读取数组大小,不要做这样的假设。接下来,检查索引:如果MATLAB中的大小真的是144x192x256,那么您应该索引
    (k*192+j)*144+i
    。但这与seg故障没有区别。
    idx_row_major = (x*WIDTH + y)*DEPTH + z
    idx_col_major = (y*HEIGHT + x)*DEPTH + z
    
    #include "mex.h"
    
    void mexFunction(int  nlhs , mxArray *plhs[],
            int nrhs, mxArray const *prhs[]){
       // check amount of inputs
       if (nrhs!=1) {
            mexErrMsgIdAndTxt("matrixIn:InvalidInput", "Invalid number of inputs to MEX file.");
        }
    
       // check type of input
       if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0])){
            mexErrMsgIdAndTxt("matrixIn:InvalidType",  "Input matrix must be a double, non-complex array.");
       }
    
       // extract the data
       double const * const matrixAux= static_cast<double const *>(mxGetData(prhs[0]));
    
       // Get matrix size
       const mwSize *sizeInputMatrix= mxGetDimensions(prhs[0]);
    
       // allocate array in C. Note: its 1D array, not 3D even if our input is 3D
       double*  matrixInC= (double*)malloc(sizeInputMatrix[0] *sizeInputMatrix[1] *sizeInputMatrix[2]* sizeof(double));
    
    
       // MATLAB is column major, not row major (as C). We need to reorder the numbers
       // Basically permutes dimensions   
    
       // NOTE: the ordering of the loops is optimized for fastest memory access! 
       // This improves the speed in about 300% 
    
        const int size0 = sizeInputMatrix[0]; // Const makes compiler optimization kick in
        const int size1 = sizeInputMatrix[1];
        const int size2 = sizeInputMatrix[2];
    
        for (int j = 0; j < size2; j++)
        {
            int jOffset = j*size0*size1; // this saves re-computation time
            for (int k = 0; k < size0; k++)
            {
                int kOffset = k*size1; // this saves re-computation time
                for (int i = 0; i < size1; i++)
                {
                    int iOffset = i*size0; 
                    matrixInC[i + jOffset + kOffset] = matrixAux[iOffset + jOffset + k];
                }
            }
        }
    
        // we are done!
    
        // Use your C matrix here
    
        // free memory
        free(matrixInC);
        return;
    }