犰狳 + Matlab Mex 段错误

Posted

技术标签:

【中文标题】犰狳 + Matlab Mex 段错误【英文标题】:Armadillo + Matlab Mex segfault 【发布时间】: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)编译和运行良好,一个简单的测试文件也会在运行时出现段错误。

【问题讨论】:

【参考方案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 你打算写一个答案吗?这与目前提出的第二种解决方案有何不同?为什么要包含编译文件的源代码?

以上是关于犰狳 + Matlab Mex 段错误的主要内容,如果未能解决你的问题,请参考以下文章

Octave:可以编译 mex,但出现错误:“无法安装 .mex 文件功能”

如何传递 matlab::data::TypedArray<double> 作为指针在 MATLAB mex 文件中构造犰狳矩阵?

用于在 Windows 中的犰狳中构建 armaMex_demo.cpp 的 Matlab mex 命令

为啥这段代码(在 Matlab 的 MEX 文件中使用 OpenMP)给出不同的结果?

在matlab中使用mex + armadillo时pinv返回svd失败

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