lapacke入りのlapackのソースビルド
初めに
lapackは数値線形代数のルーチンをがそろったfortranのライブラリです。線型方程式や線型最小二乗問題、固有値問題、特異値問題等の問題を解くことができます。
管理者権限がある場合
もしあなたが管理者権限を持っている場合は、lapackの利用は簡単です。
sudo apt -y install libatlas3-base libatlas-base-dev
でできるでしょう。
apt-cache search lapack
で必要なライブラリを探すのも一つの手でしょう。
管理者権限がない場合
ですが管理者権限がない環境において上記のinstallはできません。もちろん管理者に依頼したり、dockerやanacondaなどの仮想環境を用いて、実行するといったことも良い手段と考えられます。そして多くのスパコンでは専用にチューニングされたlapackがinstallされているものなのでそれらを利用することが速度向上に一番良い手段だと思われます。ですが諸事情によりローカル環境にlapackをinstallしなければいけないことが生じた場合、ローカルフォルダにソースビルドする必要があります。ここではその方法を紹介します。
コードのinstall
lapackの公式ページよりコードをinstallします。2024年3月現在の最新バージョンは、3.12.0です。
wget https://github.com/Reference-LAPACK/lapack/archive/refs/tags/v3.12.0.tar.gz
tar -xf v3.12.0.tar.gz
cd lapack-3.12.0
mkdir build
cd build
ここでinstallするdirectoryを指定します。ここでは、$HOME/.local以下にinstallする例を紹介します。
cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local/lapack-3.12.0 -DCBLAS:BOOL=ON -DLAPACKE:BOOL=ON -DBUILD_TESTING=ON -DLAPACKE_WITH_TMG:BOOL=ON -DBUILD_SHARED_LIBS:BOOL=ON ../
このコマンドを実行するとconfigureが進みます。このとき注意するべきなのは、condaなどの仮想環境を切ることです。仮想環境の中で実行するとfortranなどのコンパイラを見つけることができず、configureに失敗することがあります。
-- Configuring done
-- Generating done
-- Build files have been written to: /somewhere/your/build/directory
のように表示され、configureが無事に終わったら、buildに移ります。
make -j5 # ご自身の実行環境に合わせて並列数をご変更ください。
次にtestをします:
ctest
テストが無事に通っていることを確認したら、installします。
make install
このコマンドが成功すれば無事にinstall成功です。
環境変数の設定
続いて環境変数を設定します。今回shared libraryとしてinstallしたので、実行時に動的リンクを実現するための環境変数を与える必要があります。またc/c++で生のlapackを呼び出すのではなく、lapackeを経由してlapackの関数を呼び出す場合はコンパイラにincludeファイルのpathを事前に示しておくと便利です。
ホームディレクトリの.bashrc
に以下を追記します。
export CPATH="$CPATH:$HOME/.local/lapack-3.12.0/include"
export LIBRARY_PATH="$HOME/.local/lapack-3.12.0/lib:$LIBRARY_PATH"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/lapack-3.12.0/lib"
CPATH
はコンパイルする際に"-I"で指定する値を制御し、LIBRARY_PATH
はコンパイルする際に"-L"で指定する値を制御します。LD_LIBRARY_PATH
は実行時の動的リンクの参照に使われます。
※環境によっては$HOME/.local/lapack-3.12.0/lib
ではなく$HOME/.local/lapack-3.12.0/lib64
となる場合があります。ご注意ください。
それでは現在のshellに変更を反映させましょう:
source ~/.bashrc
これでinstallは完全に完了です。システムの中でlapackを利用できるようになりました。
実行テスト
最後に、以上のinstallが本当にうまくいったかを確認するテストコードを紹介します。ここではlapackのCのインターフェースであるlapackeも同時にinstallすることができたので、lapacke経由でlapackを呼び出しうまく動くかを、確認することにします。扱う問題は連立方程式
連立方程式を求めるルーチンはdgesv
があり、ここでは
#include <iostream>
#include <lapacke.h>
#include <vector>
#include <random>
/**
* Ax = b (A: NxN 正方ランダム行列 b: Nx1 ランダムベクトル)の連立方程式を解くsolver
*/
int main(int argc, char *argv[])
{
std::random_device seed;
std::uniform_real_distribution<double> rand(1,100);
int N = 2;//std::stoi(argv[1]);
std::vector<double> A(N*N); // lapackにポインタ渡しでデータを受け渡す関係により2次元配列が使えないことに注意
std::vector<double> b(N);
for (int i=0; i < N; ++i)
{
for (int j=0; j < N; ++j)
{
A[i+ j*N] = rand(seed); // col majorで配列を作る
}
b[i] = rand(seed);
}
std::cout << "A:"<<std::endl;
for (int i=0; i < N;++i)
{
for (int j=0; j < N;++j)
{
std::cout << A[i + N*j] <<",";
}
std::cout << std::endl;
}
std::cout << "b: " << std::endl;
for (int i = 0; i < N; ++i)
{
std::cout << b[i] << ",";
}
std::cout << std::endl;
int lda = N, ldb= N;
std::vector<int> ipiv(N);
int info = LAPACKE_dgesv(LAPACK_COL_MAJOR, N, 1, A.data(),lda,ipiv.data(), b.data(), ldb);
std::cout << "result:" <<std::endl;
for (auto val: b)
{
std::cout << val << ",";
}
std::cout << std::endl;
}
コンパイルは、もし前述の環境変数を正しく定義できていれば、
g++ random_matrix_gesv.cpp -o random_matrix_gesv -llapacke
でできるでしょう。
./random_matrix_gesv
で実行すると、たとえば
A:
95.9187,36.6535,54.1246,
86.55,65.2295,76.3748,
65.0626,85.4263,49.6844,
b:
99.0266,33.4126,16.6438,
result:
2.0314,-0.532306,-1.40993,
と出力されるでしょう。これが正しいかは以下のpythonコードで確かめることができます。といってもnumpyは裏でlapackを呼ぶので厳密には検証にはなっていません。
import numpy as np
A = np.array([
95.9187, 36.6535, 54.1246,
86.55, 65.2295, 76.3748,
65.0626, 85.4263, 49.6844,
]).reshape((3, 3)) # A: をコピペする
b = np.array([
99.0266, 33.4126, 16.6438,
])
x = np.linalg.solve(A, b)
print(x)
このコードを実行すると、
python test.py
[ 2.03140159 -0.53230578 -1.40993061]
と出力されるでしょう。これで検証完了です。
終わりに
ここまで読んでいただき、ありがとうございました。今回はlapackをソースビルドする方法について、説明しました。この記事のモチベーションは、私がinstallしようとした際にかなりてこずったことにあります。lapackのソースのreadme.mdにはinstall方法が書いてある一方で、それ通りにやってもlapackのC言語ラッパーであるlapackeがinstallされず、静的ライブラリとしてビルドされてしまいました。
私はlapackeが利用したかったのですが、どこを探してもlapackeのinstall方法が書いておらず、よくわかりませんでした。しかしその後installしたファイルを見ていると.travis.yml
があることを発見しました。travisはライブラリなどの自動テストのためのツールなのですが、自動テストを開始するにはもちろんコンパイルをしなければならないので、その中にビルド方法が書いてあったというわけです。今回紹介したビルド方法はそれを参考に作成しました。
皆さまの研究・開発が一層進むことを祈りまして、本記事を終えようと思います。
Discussion