犰狳 + Matlab Mex 段错误
Armadillo + Matlab Mex segfault
我折腾了一整天,所以我想我的经验可能会让大家受益,请看下面我的回答。
我首先遇到了在 Matlab 中 运行 编译的 Mex 文件的问题,因为 Matlab 抱怨它无法打开共享库 libarmadillo
。我 使用环境变量 LD_LIBRARY_PATH
和 LD_RUN_PATH
(osx 中的 DYLD_LIBRARY_PATH
和 LYLD_RUN_PATH
)。
然而,问题仍然存在,一个简单的测试文件会在 运行 时间发生段错误,即使完全相同的代码可以编译并且 运行 在 Matlab 之外(不是 Mex'd)很好。
段错误似乎是由 Matlab 在其捆绑的 LAPACK 和 BLAS 库中使用 64 位整数(long long
或 int64_t
)引起的。另一方面,犰狳默认使用 32 位整数(64 位平台上的常规 int
,或 int32_t
)。
有两种解决方法;第一个涉及强制 Matlab 改为 link 到系统库(使用 int
s),第二个涉及更改 Armadillo 的配置文件以使用 BLAS 启用 long long
s。我倾向于认为第一种比较靠谱,因为没有黑盒效应,但是也比较麻烦,需要手动安装,记住你的BLAS和LAPACK库的路径。
这两种解决方案都要求我停止使用 Armadillo 的共享库并linked/included 手动获取源代码。
为此,您必须简单地在您的系统上安装 LAPACK 和 BLAS(如果它们还没有,在 Ubuntu 中就是 libblas-dev
和 liblapack-dev
),然后复制整个 includes
目录在某个合理的地方,例如 $HOME/.local/arma
。
解决方案 1:link访问系统库
在 matlab 控制台中,将环境变量 BLAS_VERSION
和 LAPACK_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 将 link 到其捆绑的 LAPACK 和 BLAS 库,但这次 Armadillo 不会出现段错误,因为它使用了正确的字长。和以前一样,如果你想删除 -compatibleArrayDims
.
,你也可以取消注释 ARMA_64BIT_WORD
编译为
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;
}
我折腾了一整天,所以我想我的经验可能会让大家受益,请看下面我的回答。
我首先遇到了在 Matlab 中 运行 编译的 Mex 文件的问题,因为 Matlab 抱怨它无法打开共享库 libarmadillo
。我 LD_LIBRARY_PATH
和 LD_RUN_PATH
(osx 中的 DYLD_LIBRARY_PATH
和 LYLD_RUN_PATH
)。
然而,问题仍然存在,一个简单的测试文件会在 运行 时间发生段错误,即使完全相同的代码可以编译并且 运行 在 Matlab 之外(不是 Mex'd)很好。
段错误似乎是由 Matlab 在其捆绑的 LAPACK 和 BLAS 库中使用 64 位整数(long long
或 int64_t
)引起的。另一方面,犰狳默认使用 32 位整数(64 位平台上的常规 int
,或 int32_t
)。
有两种解决方法;第一个涉及强制 Matlab 改为 link 到系统库(使用 int
s),第二个涉及更改 Armadillo 的配置文件以使用 BLAS 启用 long long
s。我倾向于认为第一种比较靠谱,因为没有黑盒效应,但是也比较麻烦,需要手动安装,记住你的BLAS和LAPACK库的路径。
这两种解决方案都要求我停止使用 Armadillo 的共享库并linked/included 手动获取源代码。
为此,您必须简单地在您的系统上安装 LAPACK 和 BLAS(如果它们还没有,在 Ubuntu 中就是 libblas-dev
和 liblapack-dev
),然后复制整个 includes
目录在某个合理的地方,例如 $HOME/.local/arma
。
解决方案 1:link访问系统库
在 matlab 控制台中,将环境变量 BLAS_VERSION
和 LAPACK_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 将 link 到其捆绑的 LAPACK 和 BLAS 库,但这次 Armadillo 不会出现段错误,因为它使用了正确的字长。和以前一样,如果你想删除 -compatibleArrayDims
.
ARMA_64BIT_WORD
编译为
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;
}