土日で C++ の復習をして、月曜日は uBlas のコードを眺めていた。 uBlas というのは boost のライブラリのうちの一つで、線形代数の数値計算のための基本的な機能を提供している。疎行列も OK。テンプレートの能力を最大限に活用した遅延評価により、一時オブジェクトの生成を極力押えることができる。
テンプレートを使いまくった C++ のコードって、他人が理解するのは非常に難しいということを実感した。というか、uBlas のコードってメンテナンス可能だとは思えないんだけど。こんなもんなんだろうか。
uBlas を使う上での注意点。
デフォルトではライブラリの色んなところで assert が呼ばれる。バグを見つけるのには便利だけど、その分 遅くなる。バグが無くなったと思ったら、オプション -DNDEBUG をつけて再コンパイルする。
行列同士のかけ算は prod(mat1, mat2) なんだけど、以下のようなコードは現在のバージョン boost-1.33.1 ではコンパイル時にエラーになる。boost user - uBLASによれば以前はできたらしい。
prod(mat1, prod(ma2, mat3));
この例だと一時オブジェクトを作らざるを得ないから、それよりかエラーにすることを選んだのか。
以下のようなコードでは、一時オブジェクトが生成されてしまう。
v3 = prod (Mat, v1) + v2;
右辺に v3 が使われているかどうか、コンパイラにはわからないので、v3 の内容を壊さないために、右辺の内容をいったん 一時オブジェクトに格納する必要があるから。v3 が右辺に無いことをコンパイラに教えるには、以下のように noalias を使う。
noalias(v3) = prod (Mat, v1) + v2;
と書く。この例だと、一時オブジェクトは全く生成されない。右辺のベクトルの各成分を計算した結果は、直接 v3 に格納される。prod (Mat, v1) + v2 は式オブジェクトを生成し、noalias(v3) = の代入演算子が呼ばれた時点で、右辺のベクトルが実際に計算される。その「実際の計算」が書かれているコードは functional.hpp。
僕がやりたい計算は提供されている線形代数の演算だけでは実現できないので、どのライブラリを使うにしても中を覗く必要があるんだけど、uBlas は強烈。
とてもおもしろい。
最近のコメント