Boostライブラリーの利用
インストール
ページ添付の Boost-1.85.0 をダウンロード(自称6バイトですが,実際には34982722 バイトあるので注意)してインストールしてください.
- HomeBrewとかMacPortを使っている人は,これをインストールするとトラブルの元ですので,自分でなんとかしてください.
-
トラブルとは, HomeBrew環境を使っているのか?Macの環境を使っているのか?訳がわからなくなりがち,ということです.使うだけならともかく,C++でコンパイルするとなると大変
-
-
添付のものは,HomeBrewとかMacPortのように「Mac上にLinuxのコピーを作成して,互換性がある巨大なシステム全体を構築する」のではなく,「とりあえーずMacにある程度揃っているから,そこでまあまあ動くものをちょいっと使う」というポリシーのものです.
-
システム全体を一度インストールすると,なんと,管理しなければならないのです.Appleの「更新があるからアップデートしてね」が面倒に思えるタイプの人には不適当です.だって,ダブル・トリプルで維持管理しないとだし
-
システム全体を一度インストールすると,ファイルがでかいです.だって,OSをダブル・トリプルでインストールするので
-
Boostの内容は非常に多いですが, まあ主だったものは
- 多次元配列 Array, 特殊関数 Function, 統計関数 Math, 幾何学計算 Geometry, 微積分などの Argorithm 乱数 Random...
- 日付と時刻 Chrono, DateTime...
- インターネット通信 Asio Webサイト通信 Beast プロセス間通信 Process, 並列計算 MPI,
いや,多すぎてわからん.テストのために,いくつか使ってみましょう.
利用例1
動作確認を兼ねて,日付や時刻にアクセスしてみましょう.
初めてのBoost
猿に願ってみた:
だが,インストールしたBoostを「使う設定」を行なってないので
エラーが出て動かない・・・
もちろん再生ボタンで動くようにする方法もあるのですが,そりゃ面倒なのでここで議論することにして.ここでは,CMakeでなんとかしてみましょう!すると, CMakeLists.txtを書く訳です.猿に聞いた結果,CMakeLists.txtを,以下のようにすれば良いらしい:
cmake_minimum_required(VERSION 3.10) set(CMAKE_OSX_SYSROOT macosx) project(MultiTargets) # Library Search cmake_policy(SET CMP0167 NEW) find_package(Boost REQUIRED COMPONENTS timer) ... # BOOSTターゲット add_executable(BOOST BOOST/main.cpp) ←これは,まあ従来通りやね target_link_libraries(BOOST PRIVATE Boost::timer)
とりあえずこれは,黙って書いておけば,幸運の風が吹くらしい.上の例では timer を使っているので, このようにしてtimer を探してもらうで,これが新顔で,Boost::timerライブラリを結合させる.PRIVATEを省くと,Boostらしいものを全部結合してしまい,無駄が多いらしい.
で,ターミナルを使って,ビルドと実行を行うのじゃ:
ところでプログラムの内容ですが, boost::timer::cpu_timer には start() stop() resume() があり,まあ意味はわかると思うのですが,elapsed()でstart()以来の合計時間が ナノセカンド単位で得られます.wallはあなたの部屋の壁掛け時計の経過時間(要するに実際に経過した時間),userがあなたの処理に必要であった時間です.
system時間は,例えばファイルを読み込むのにかかった時間とか,メモリーの使いすぎで遅くなった時間とか,そういう処理に必要であった時間. systemがでかいってのは,あなたの計算機の使い方が下手くそ,ということを意味しています.
コンピュータの名前とか, 日付とか
どさくさに紛れて,コンピュータの名前とかゲットしてみましょう.
#include <iostream> #include <boost/timer/timer.hpp> //cpu-time #include <boost/asio.hpp> //hostname #include <boost/date_time/posix_time/posix_time.hpp> //date-time #include <cmath> void boost_timer(){ boost::timer::cpu_timer timer; // 計測開始 // 計測したい処理 double sum = 0; for (int i = 0; i < 100000000; ++i) { sum += std::sin(i * 0.000001); } boost::timer::cpu_times elapsed = timer.elapsed(); std::cout << "user: " << elapsed.user / 1e9 << " sec" << std::endl; std::cout << "system: " << elapsed.system / 1e9 << " sec" << std::endl; std::cout << "wall: " << elapsed.wall / 1e9 << " sec" << std::endl; boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); boost::asio::io_context io; std::string hostname = boost::asio::ip::host_name(); std::cout << now << " on " << hostname << std::endl; } int main() { boost_timer(); return 0; }
このへんがホスト名を取得するコード,この辺が日付を取得するコードです(POSIXってのは, コンピュータは「このように動作するべきである」という規格で, Windows以外はほぼPOSIX準拠です).こうしとくと
arm64:build $ make BOOST [ 50%] Building CXX object CMakeFiles/BOOST.dir/BOOST/main.cpp.o [100%] Linking CXX executable BOOST [100%] Built target BOOST arm64:build $ ./BOOST user: 0.27 sec system: 0 sec wall: 0.28 sec 2025-Jul-01 16:35:19 on Core-9.local
こうなります.もちろん,ここが日付で,ここがコンピュータの名前です.
利用例2
Boostを使えば,乱数やら様々な関数を簡単に利用できます.
乱数
いやもう,猿に聞けばいいだけ
まあ聞いたら答えが返ってくるから,ここで練習する必要なさげ・・・
特殊関数
Boostでは著しく多くの特殊関数が利用できます.ま,猿に聞くだけですね:
利用例3
Boostの使い方に慣れたところで, 多次元配列Arrayを利用しましょう.
Boostによる 多次元配列
では当初の目標である多次元配列を使いましょう:
...
#include <boost/multi_array.hpp> //multi-array
...
boost::multi_array<double,3> A3(boost::extents[3][4][5]);
std::cout << "A3 Dimension= " << A3.num_dimensions() << " Elements= " << A3.num_elements() << std::endl;
for(int ndim=0;ndim<A3.num_dimensions();++ndim)
std::cout << "A3 " << ndim << "-th max index=" << A3.shape()[ndim] << std::endl;
A3[0][0][0] = 666.;
A3[1][1][1] = 999.;
A3[2][3][4] = -123;
std::cout << "A3[0][0][0]=" << A3[0][0][0] << std::endl;
std::cout << "A3[1][1][1]=" << A3[1][1][1] << std::endl;
std::cout << "A3[2][3][4]=" << A3[2][3][4] << std::endl;
for (int i = 0; i < A3.num_elements(); ++i)
if (A3.data()[i]!=0) std::cout << "A3(" << i << ")=" << A3.data()[i] << std::endl;
これで多次元配列ができます.この例では3次元配列を作っています. で, [3][4][5]が,各次元の配列寸法になります.ここにあるように,A3[i][j][k]でアクセスできますが,添字の範囲は\[0\leq i < 3,\ 0\leq j < 4,\ 0\leq k < 5\]になります.まあ,そうは言っても,\(3\times 4\times 5=\mathsf{A3.num\_elements()}=60\)個の要素があるだけですので,このようにして1次元的にアクセスすることも可能です.この辺では,0ではない要素だけ画面に出力しています.
さて, Boost::multi_arrayは,添字範囲を平行移動することができます!
// index_bases()を追加すれば,添字の範囲を変更可能
boost::array<boost::multi_array<double, 3>::index, 3> A3_base = {{5, 4, -5}};
A3.reindex(A3_base);
for (int ndim = 0; ndim < A3.num_dimensions(); ++ndim)
std::cout << "A3 " << ndim << "-th max index=" << A3.shape()[ndim]
<< " shifted to " << A3.index_bases()[ndim] << std::endl;
std::cout << "A3[5][4][-5]=" << A3[5][4][-5] << std::endl;
std::cout << "A3[6][5][-4]=" << A3[6][5][-4] << std::endl;
std::cout << "A3[7][7][-1]=" << A3[7][7][-1] << std::endl;
std::cout << "A3[8][8][0]=" << A3[8][8][0] << std::endl;
まずこれで平行移動量を定義,で,これで既存の配列に適用しています.すると,こういうふうに添字の範囲が平行移動する訳ですね!
で,そもそも\(3\times 4\times 5\)サイズの配列を\((5,4,-5)\)だけ平行移動しただけなので,こやつは,配列の範囲をオーバーしています.このときの挙動は, CMakeLists.txt の設定で異なります.
デフォルト(デバッグモード)の挙動
デフォルトでは,CMAKE_BUILD_TYPE=Debug と設定されているのです.プログラム開発用のデバッグ設定ですね!CMakeLists.txt の中で明示的に書くなら
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_OSX_SYSROOT macosx)
project(MultiTargets)
# Build-Modeの設定
set(CMAKE_BUILD_TYPE Debug)
この場合,このように配列の範囲外にアクセスしようとすると,
arm64:build $ ./BOOST
A3 Dimension= 3 Elements= 60
A3 0-th max index=3
A3 1-th max index=4
A3 2-th max index=5
A3[0][0][0]=666
A3[1][1][1]=999
A3[2][3][4]=-123
A3(0)=666
A3(26)=999
A3(59)=-123
A3 0-th max index=3 shifted to 5
A3 1-th max index=4 shifted to 4
A3 2-th max index=5 shifted to -5
A3[5][4][-5]=666
A3[6][5][-4]=999
A3[7][7][-1]=-123
Assertion failed: (size_type(idx - index_bases[0]) < extents[0]), function access, file base.hpp, line 136.
A3[8][8][0]=Abort trap: 6
このように,エラーしてくれます!便利ですね〜
リリースモードでの挙動
でも,実際に研究するときにはエラーチェックは不要で,実行が遅いデバッグモードではなく,リリースモードを使いましょう.
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_OSX_SYSROOT macosx)
project(MultiTargets)
# Build-Modeの設定
set(CMAKE_BUILD_TYPE Release)
この場合,このように配列の範囲外にアクセスしても
...
A3 2-th max index=5 shifted to -5
A3[5][4][-5]=666
A3[6][5][-4]=999
A3[7][7][-1]=-123
A3[8][8][0]=0
間違ったままで,何も起こりません.要するに,バグに気づくことはない.ということになります.
Releaseモードでは,添字のチェックを省略する以外に,さまざまな最適化が行われ,安全性よりも計算速度を上昇させます.
NlohmanJSONライブラリーの利用
いいよねこれ
VTKライブラリーの利用
ここで説明するべきですかね?
添付 | サイズ |
---|---|
boost_1_85_0-osx15.3.2.pkg | 6 バイト |