前言
最近在用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;
}