【问题标题】:Armadillo + Matlab Mex segfault犰狳 + Matlab Mex 段错误
【发布时间】:2015-02-10 00:14:48
【问题描述】:

我整天都在摆弄这个,所以我想我可以让每个人都从我的经验中受益,请在下面查看我的答案。

我第一次在 Matlab 中运行已编译的 Mex 文件时遇到问题,因为 Matlab 抱怨它无法打开共享库 libarmadillo。我solved this 使用环境变量LD_LIBRARY_PATHLD_RUN_PATHDYLD_LIBRARY_PATHLYLD_RUN_PATH 在osx 中)。

但是问题仍然存在,即使完全相同的代码在 Matlab 之外(不是 Mex'd)编译和运行良好,一个简单的测试文件也会在运行时出现段错误。

【问题讨论】:

    标签: matlab segmentation-fault lapack blas armadillo


    【解决方案1】:

    段错误似乎是由于 Matlab 在其捆绑的 LAPACK 和 BLAS 库中使用 64 位整数(long longint64_t)引起的。另一方面,犰狳默认使用 32 位整数(在 64 位平台上为常规 int,或 int32_t)。

    有两种解决方案;第一个涉及强制 Matlab 链接到系统的库(使用 ints),第二个涉及更改 Armadillo 的配置文件以使用 BLAS 启用 long longs。我倾向于认为第一个更可靠,因为没有黑盒效果,但也比较麻烦,因为你需要手动安装并记住你的 BLAS 和 LAPACK 库的路径。

    这两种解决方案都要求我停止使用 Armadillo 的共享库并手动链接/包含源代码。 为此,您必须简单地在您的系统上安装 LAPACK 和 BLAS(如果它们还没有,在 Ubuntu 中为 libblas-devliblapack-dev),然后将整个 includes 目录复制到某个合理的位置,例如在 $HOME/.local/arma 中例子。


    解决方案 1:链接到系统的库

    在 matlab 控制台中,将环境变量 BLAS_VERSIONLAPACK_VERSION 设置为指向您系统的库。就我而言(Ubuntu 14.04,Matlab R2014b):

    setenv('BLAS_VERSION','/usr/lib/libblas.so');
    setenv('LAPACK_VERSION','/usr/lib/liblapack.so');
    

    然后就可以正常编译了:

    mex -compatibleArrayDims -outdir +mx -L/home/john/.local/arma -llapack -lblas -I/home/john/.local/arma test_arma.cpp
    

    或者如果您在includes/armadillo_bits/config.hpp 中定义标志ARMA_64BIT_WORD,则可以删除选项-compatibleArrayDims


    解决方案 2:更改 Armadillo 的配置

    第二种解决方案是取消注释 Armadillo 的配置文件 includes/armadillo_bits/config.hpp 中的标志 ARMA_BLAS_LONG_LONG。 Matlab 将链接到其捆绑的 LAPACK 和 BLAS 库,但这次 Armadillo 不会出现段错误,因为它使用了正确的字长。和以前一样,如果你想删除-compatibleArrayDims,也可以取消注释ARMA_64BIT_WORD

    【讨论】:

    • 这是不正确的:“默认使用 32 位版本的 [LAPACK]”。您混淆了两个独立的问题:整数大小(32 位和 64 位)和指令集(x86/ia32 与 x86-64)。它们是相关的,但不是一回事。默认情况下,犰狳将使用 int 作为内部整数变量,在大多数系统上是 32 位的(即使在 x86-64 Linux 上也是如此)。定义 ARMA_64BIT_WORD 只是强制内部整数为 64 位。一些 LAPACK 实现(如 MATLAB 的)将其作为默认值,有些则没有(即使它们是为 x86-64 系统编译的)。
    • @mtall 抱歉,如果您发现这令人困惑,感谢您指出这一点;正如我所说,ARMA_64BIT_WORD 只是为了摆脱-compatibleArrayDims,它修复了段错误。关于目标架构,如果不是 32/64 位不匹配,我无法解释段错误,以及it has been suggested somewhere else。但如果您能就您认为幕后真实发生的事情分享更详细的解释,我将不胜感激。
    • Matlab 自带的 LAPACK 可能与标准 LAPACK 的 ABI 不同,可能是因为整数宽度不同。标准 LAPACK 使用 int(即使在 64 位机器上),而看起来 Matlab 的 LAPACK 使用 long long。启用 ARMA_BLAS_LONG_LONG 会导致 Armadillo 在将数据传递给 BLAS 和 LAPACK 函数时使用 64 位整数。
    【解决方案2】:

    编译

    mex -larmadillo -DARMA_BLAS_LONG_LONG armaMex_demo2.cpp
    

    (在 Matlab 中)

    armaMex_demo2(rand(1))
    

    没有段错误。

    但是,编译时使用

    mex -larmadillo  armaMex_demo2.cpp
    

    (在 Matlab 中)

    armaMex_demo2(rand(1))
    

    导致段错误。

    这里是 armaMex_demo2.cpp

    /* ******************************************************************* */
    // armaMex_demo2.cpp: Modified from armaMex_demo.cpp copyright Conrad Sanderson and George Yammine.
    /* ******************************************************************* */
    // Demonstration of how to connect Armadillo with Matlab mex functions.
    // Version 0.2
    // 
    // Copyright (C) 2014 George Yammine
    // Copyright (C) 2014 Conrad Sanderson
    // 
    // This Source Code Form is subject to the terms of the Mozilla Public
    // License, v. 2.0. If a copy of the MPL was not distributed with this
    // file, You can obtain one at http://mozilla.org/MPL/2.0/.
    /////////////////////////////
    #include "armaMex.hpp"
    
    
    void
    mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
      /* 
         Input:   X (real matrix)
         Output:  Eigenvalues of X X.T
      */
    
    
      if (nrhs != 1)
        mexErrMsgTxt("Incorrect number of input arguments.");
    
    
      // Check matrix is real
      if( (mxGetClassID(prhs[0]) != mxDOUBLE_CLASS) || mxIsComplex(prhs[0]))
        mexErrMsgTxt("Input must be double and not complex.");
    
    
      // Create matrix X from the first argument.
      arma::mat X = armaGetPr(prhs[0],true);
    
    
      // Run an arma function  (eig_sym)
      arma::vec eigvals(X.n_rows);
      if(not arma::eig_sym(eigvals, X*X.t()))
        mexErrMsgTxt("arma::eig_sym failed.");    
    
    
      // return result to matlab
      plhs[0] = armaCreateMxMatrix(eigvals.n_elem, 1);
      armaSetPr(plhs[0], eigvals);
    
      return;
    }
    

    【讨论】:

    • 你能解释一下你的答案吗?你定义什么符号,为什么它很重要?它还有什么作用?有没有可以链接到的错误报告?
    • @tar 你打算写一个答案吗?这与目前提出的第二种解决方案有何不同?为什么要包含编译文件的源代码?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 1970-01-01
    相关资源
    最近更新 更多