メインコンテンツに移動

ライブラリーの利用

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ライブラリーの利用

ここで説明するべきですかね?

 

File attachments
添付 サイズ
boost_1_85_0-osx15.3.2.pkg 6 バイト