mex 运行时错误:必须使用“-largeArrayDims”选项重建使用稀疏矩阵的 64 位 mex 文件

Posted

技术标签:

【中文标题】mex 运行时错误:必须使用“-largeArrayDims”选项重建使用稀疏矩阵的 64 位 mex 文件【英文标题】:mex runtime error: 64-bit mex files using sparse matrices must be rebuilt with the "-largeArrayDims" option 【发布时间】:2015-04-13 09:08:25 【问题描述】:

我的 c 代码应该将 Matlab 稀疏格式转换为 TAUCS 格式,这也是列主要格式。

当然,我是在 Matlab 本身中生成 Matlab 稀疏格式,然后将其传输到 mex 文件中。

代码编译良好。但是,当我尝试运行 Matlab 时,出现以下运行时错误:

Error using MatSparse_2_TAUCS
Function "mxGetJc_700" is obsolete.
(64-bit mex files using sparse matrices must be rebuilt with the "-largeArrayDims" option.  See the R2006b release notes for more details.)

Error in Matlab_mex_Testing (line 18)
    z = MatSparse_2_TAUCS(x, spMat);

我认为我已经在我的 make 文件中使用了“-largeArrayDims”选项。

这是我的 Matlab 代码:

Dir  = '/home/dkumar/Mex_Codes_DKU/MexCode_Working/Mex_CPP_N_ARMADILLO_Codes_DKU_makefile_Working';

%Create a simple sparse matrix
spMat = speye(100, 100);
%Set few more elements to be non-zero
spMat(5, 8)   = 1.500;
spMat(5, 100) = 3.500;
spMat(19, 100) = 3.500;
spMat(59, 89)   = 1.500;

% MEX
cd(Dir);
x = 5.0;
z = MatSparse_2_TAUCS(x, spMat);

这是我的 C 代码:

    #include "mex.h"
#include <math.h>
#include <stdio.h>

#include "/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/taucs.h"

extern void _main();

const int numInputArgs  = 2;
const int numOutputArgs = 1;

// Function declarations.
// -----------------------------------------------------------------

int TestingLibraries() ;   // declared and defined in In Include_4_TSNNLS.c and Include_4_TSNNLS.h


// Function definitions.
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[],
          int nrhs, const mxArray *prhs[]) 

    double *y, *z, x;

    /* Declare variable */
    mwSize mrows,ncols;
    int status;
    mwSize nzmax;
    mwIndex *irs,*jcs,j,k;

    /*  Check for proper number of arguments. */
    if (nrhs != 2) 
        mexErrMsgTxt("Two inputs required.");
    if (nlhs != 1) 
        mexErrMsgTxt("One output required.");

    /* Check to make sure the first input argument is a scalar. */
    if (!mxIsDouble(prhs[0]) ||     mxIsComplex(prhs[0]) || mxGetN(prhs[0])*mxGetM(prhs[0]) != 1) 
        mexErrMsgTxt("Input x must be a scalar.");
    

    /* Get the scalar input x. */
    x = mxGetScalar(prhs[0]);

    /* Create a pointer to the input matrix y. */
    y = mxGetPr(prhs[1]);


     /* Check data type dimensions of the matrix input y. */
    if (!(mxIsDouble(prhs[1])))
        mexErrMsgIdAndTxt( "MATLAB:DKU", "Input argument must be of type double.");
    

    if (mxGetNumberOfDimensions(prhs[1]) != 2)
        mexErrMsgIdAndTxt( "MATLAB:DKU", "Input argument must be two dimensional\n");
    

     /* Get the size and pointers to input data */
    mrows =mxGetM(prhs[1]);
    ncols = mxGetN(prhs[1]);

    // Declaring the matrix in TAUCS
    taucs_ccs_matrix *A;

    // Verify the matrix y is infact sparse
    if (!(mxIsSparse(prhs[1])))
        mexErrMsgIdAndTxt( "MATLAB: DKU", "Input matrix is not sparse\n");
    else
        //Work with irs and jcs directly instead of row-column pairs that are less compact.  
        double* sr      = mxGetPr(prhs[1]);   
        jcs         = mxGetJc(prhs[1]);     
        irs         = mxGetIr(prhs[1]);

    // Now converting sparse matrix to TAUCS format
        A       = (taucs_ccs_matrix*)malloc(sizeof(taucs_ccs_matrix));
        A->n        = ncols;
        A->m        = mrows;   
        A->flags    = TAUCS_DOUBLE;

        // Allocating spaces
        int nnz     = jcs[ncols]; 
        A->colptr       = (int*)mxMalloc(sizeof(int)*(A->n+1));
        A->rowind       = (int*)mxMalloc(sizeof(int)*nnz);
        A->values.d     = (double*)mxMalloc(sizeof(taucs_double)*nnz);  

        int icolOffset = 0;  // both matlab "SPARSE" indices and TAUCS  "SPARSE" indices start with 0 

    A->colptr   = jcs-icolOffset;
        A->rowind   = irs-icolOffset;
        A->values.d     = sr;
    


    /* Create a C pointer to a copy of the output matrix. */
     //memcpy(mxGetPr(plhs[0]), &A, sizeof(A)); 

    //Freeing spaces
    mxFree(A->colptr);
    mxFree(A->rowind);
    mxFree(A->values.d);  

    //Creating plhs: just some fake value
   mwSize sz[2];
   sz[0] = mrows  ; // Matlab is row first
   sz[1] = ncols  ;
   plhs[0] = mxCreateNumericArray(2, sz, mxDOUBLE_CLASS, mxREAL);
   //Get a pointer to pOUT
   double* p2 = (double*)mxGetData(plhs[0]);
   // just copying input matrix
   int i1;

   for (i1 =0; i1 < mrows*ncols; i1++)
   
    *p2 = *y;
         p2++; y++;
   


这是我的生成文件:

  MEXSUFFIX  = mexa64
  MATLABHOME = /usr/local/MATLAB/R2011b
  MEX        = /usr/local/MATLAB/R2011b/bin/mex
  CXX        = gcc
  CFLAGS     = -fPIC -pthread -DMX_COMPAT_32 \
               -DMATLAB_MEX_FILE  -largeArrayDims


  LIBS      = -lm
  INCLUDE   = -I$(MATLABHOME)/extern/include
  MEXFLAGS  = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)' -largeArrayDims

  REBUILDABLES = *.o *.mexa64     ## Anything with these extension
  TARGET = MatSparse_2_TAUCS.$(MEXSUFFIX)

  all : $(TARGET)
    echo All done

  clean : 
    rm -f $(REBUILDABLES)   
    echo Clean done

  $(TARGET): MatSparse_2_TAUCS.o
    $(MEX) $(MEXFLAGS) $(LIBS) -output MatSparse_2_TAUCS $^

  MatSparse_2_TAUCS.o: Include_4_TSNNLS.c MatSparse_2_TAUCS.c
    $(CXX) $(CFLAGS) $(INCLUDE) -c $^

另外,当我运行我的 makefile 时,我收到了一些关于 memcpy 的警告:

Output of make:

$ make
gcc -fPIC -pthread -DMX_COMPAT_32 -DMATLAB_MEX_FILE  -largeArrayDims -I/usr/local/MATLAB/R2011b/extern/include -c Include_4_TSNNLS.c MatSparse_2_TAUCS.c
MatSparse_2_TAUCS.c: In function ‘mexFunction’:
MatSparse_2_TAUCS.c:98:6: warning: incompatible implicit declaration of built-in function ‘memcpy’ [enabled by default]
      memcpy(mxGetPr(plhs[0]), &A, sizeof(A)); 
      ^
/usr/local/MATLAB/R2011b/bin/mex -cxx CC='gcc' CXX='gcc' LD='gcc' -largeArrayDims -lm -output MatSparse_2_TAUCS MatSparse_2_TAUCS.o

Warning: You are using gcc version "4.8.2-19ubuntu1)".  The version
         currently supported with MEX is "4.3.4".
         For a list of currently supported compilers see: 
         http://www.mathworks.com/support/compilers/current_release/

echo All done
All done

我们将不胜感激。

更新:

关于 TAUCS 或 taucs_ccs_matrix page 12 of the link的信息

根据@chappjc 的建议更新了 c 代码

【问题讨论】:

您应该使用mxSetPr(plhs[0], &amp;A) 之类的东西(未经测试,但应该是这样的)。 taucs_ccs_matrix 类型是什么? 添加了更多关于 taucs_ccs_matrix 的信息 除了你没有创建输出plhs[0],你不能只是将C结构复制到double*。你可以而且应该在没有memcpy 的情况下这样做,除非你确定你知道自己在做什么...... @chappjc 感谢您提醒我的错误。我删除了“memcpy”的使用并创建了 plhs[0]。你能检查我的makefile,看看我做错了什么吗?我真的很感激。 【参考方案1】:

CFLAGS 中定义MX_COMPAT_32mex 命令的-largeArrayDims 选项不兼容。事实上,它的作用恰恰相反。我在this post 底部附近记录了这些选项的工作原理。实际上是-compatibleArrayDims 选项设置了MX_COMPAT_32,这是你不想要的。

还要注意-largeArrayDimsmex 命令的一个选项,所以它继续MEXFLAGS 而不是CFLAGS。我很确定 gcc 不知道如何处理该开关。只是不要定义MX_COMPAT_32

如果您想坚持使用 32 位索引,您可以尝试设置 MX_INTERNAL_730 并保留 MX_COMPAT_32,但不要这样做。

【讨论】:

【参考方案2】:

更改 mex 编译器可能会有所帮助。我在 Windows 下使用 Visual C++ 2008 作为编译器时遇到了同样的错误消息,但通过使用 gcc 编译解决了问题。

【讨论】:

以上是关于mex 运行时错误:必须使用“-largeArrayDims”选项重建使用稀疏矩阵的 64 位 mex 文件的主要内容,如果未能解决你的问题,请参考以下文章

在 MATLAB MEX 文件中使用 Thrust 的运行时链接器错误

Matlab 错误:关于 'compile_mex;'命令

在八度音程中运行 matlab 项目时,mex 函数未定义错误

使用 Visual Studio 编译时的 MEX 选项

MATLAB + Mex + OpenCV:链接和编译正确,但在运行时找不到库

MATLAB 错误使用 mex