C++矩阵运算库armadillo配置笔记
前言
最近在用C++实现神经网络模型,优化算法需要用到矩阵操作,一开始我用的是boost的ublas库,但用着用着感觉很不习惯,接口不够友好。于是上网搜索矩阵运算哪家强,大神们都推荐armadillo
。一方面本着群众的眼光是雪亮的这一原则,另一方面也想尝尝鲜(听说和Matlab很类似,用着非常爽),就折腾了一下。
armadillo是一个开源的C++线性代数计算函数库,目的是在效率和易用性之间取个折中。它的API风格类似Matlab,因此会用matlab的话,用起它来将十分得心应手。这个库其实是对底层的矩阵运算库(例如BLAS,LAPACK)的封装,也就是说,这个库本身的计算能力其实不强,但是这个库可以配合开源的底层库来使用,例如最基本的BLAS+LAPACK或者改进后的OpenBLAS,ACML还有强大的MKL。
在Eclipse中配置armadillo
1.打开"C/C++ General" 标签下的"Paths and Symbols",在Includes菜单下的language框里选择GNU C++,点击右边的add按钮,将D:\armadillo-6.300.2\include
加入路径
2.在Libraries标签下加入BLAS和LAPACK的路径 D:\armadillo-6.300.2\examples\lib_win64
3.在C/C++ Build->Settings下,选择MinGW C++ Linker->Libraries,点击add按钮输入lapack_win64_MT
和blas_win64_MT
到D:\armadillo-6.300.2\include\armadillo_bits
下,找到config.hpp,取消以下两行的注释
#define ARMA_USE_LAPACK
#define ARMA_USE_BLAS
这里有一个问题,我写了一个测试程序,矩阵点乘、加减法能正常输出,但是矩阵乘积、行列式、求逆就没有输出,估计是哪里崩溃了。 接着我想着换别的Blas库会不会就行了呢,于是参照网上的方法,到http://icl.cs.utk.edu/lapack-for-windows/clapack/index.html 下载blas.lib,libf2c.lib,lapack.lib三个库放到lib目录(我在D:\armadillo-6.300.2下新建了一个lib目录),并将它们按照刚才的步骤加入到PATH。编译发生了错误:
ld.exe: skipping incompatible D:\armadillo-6.300.2\lib/lapack.lib when searching for -llapack
skipping incompatible D:\armadillo-6.300.2\lib/lapack.lib when searching for -llapack
skipping incompatible D:\armadillo-6.300.2\lib\lapack.lib when searching for -llapack
StackOverFlow上的说法是,这是因为用64位编译器和32位的lib文件链接导致的。后面又陆陆续续试了很多办法,都没解决程序崩溃的问题,不想浪费时间就放弃了。
armadillo+openblas配置
网上看了一些教程,写的很复杂,经过一番折腾,发现在windows下配置不用那么费劲。首先我们要去OpenBlas官网下载一个最新版的openblas库,64位系统下载OpenBLAS-v0.2.15-Win64-int32.zip
,32位系统下载OpenBLAS-v0.2.15-Win32.zip
。下载完后解压,接着打开"C/C++ General" 标签下的"Paths and Symbols",在Library Path框里点击add,加入Openblas的lib目录路径,同时把libopenblas.dll
放到C:/Windows/System32
下(或者可执行文件所在的目录),然后在C/C++ Build->Settings下,选择MinGW C++ Linker->Libraries,点击add按钮输入openblas
就完成配置了。
接下来我们写一个程序来测试一下:
#include <iostream>
#include <armadillo>
using namespace std;
using namespace arma;
int main() {
mat A = randu<mat>(5,10);
mat C = randu<mat>(10,5);
mat U = A * C;
U.print("U:");
mat V = inv(U);
V.print("V:");
double D = det(U);
cout<<"det(U)="<<D<<endl;
return 0;
}