Subscribed unsubscribe Subscribe Subscribe

OpenCV のライブラリとしての完成度についてのメモ。

ここ最近ずっと触ってきて、思ったことを書いておきます。

メモリ管理 ★★☆☆☆

  • libc の malloc() をラップするような形で独自のメモリ管理機構 (プールアロケータベース) を持っています。しかし、コンパイラの実装によらず勝手にアラインメントを計算する関数を用意していたりと、インテル発のくせに IA64 ではたしてまともに動くのか疑問 (未検証)。まあ、動くんだろうけど。
  • ルートアロケータは、cvSetMemoryManager() で設定することができます。この辺は malloc() や C++ のランタイム規定の実装に頼りがちな同類のライブラリにはない良さだと思いますが、アロケータは単純に渡されたサイズ分のメモリを確保するだけではだめなようで、ドキュメントにない quirks が必要なのです。デフォルトの実装は次のようになっていました。
// default <malloc>
static void*
icvDefaultAlloc( size_t size, void* )
{
    char *ptr, *ptr0 = (char*)malloc(
        (size_t)(size + CV_MALLOC_ALIGN*((size >= 4096) + 1) + sizeof(char*)));

    if( !ptr0 )
        return 0;

    // align the pointer
    ptr = (char*)cvAlignPtr(ptr0 + sizeof(char*) + 1, CV_MALLOC_ALIGN);
    *(char**)(ptr - sizeof(char*)) = ptr0;

    return ptr;
}

正直 size >= 4096 のときで処理をわけていたりする意図がわからん。これってどっかで発生していたバッファオーバランを quick plug する邪道技では。

  • 行列などのオブジェクトでは参照カウンタを使ってコピー・オン・ライトを実現しており、極力 blit が発生しないようにしています。
  • オブジェクトによってメモリ管理ポリシに違いがあるのが、非常に利用者を惑わせます。

モジュラリティ (モジュール度) ★★★☆☆

  • 一見するとオブジェクト指向に乗っ取ったデータモデルが提供されています。例えば CvArr という配列オブジェクトが、行列オブジェクトである CvMat やピックスマップオブジェクトである IplImage などのスーパークラスとして位置付けられています。
  • ポリモーフィズムを実現するため、オブジェクトを表現する構造体の先頭 4 バイトに型情報を持たせていることがあります。
  • しかし、全てのオブジェクトが同様の規約によって実装されているわけではないので、大変混乱します。gobject を見習ってほしい。

エラーハンドリング ★★★☆☆

大域変数に最後のエラーを突っ込むモデルを採用しています。マルチスレッド環境下では TLS をつかってそれの分離を行っています。しかし、そこで platform-specific なコードを織りまぜて TLS を使うくらいなら戻り値モデルを使った方がいくらかマシと思うのは、時代についていけてないせいでしょうか。

車輪の再発明度 ★★★★★

まあもともと research project に端を発しているので仕方ないと言えますが、でも行列演算などは BLAS などを利用すればよかっただろうし、ピックスマップにかんしてもAdobe Generic Image Lbirary などよさげなのはいくつもありますし。「それらをまとめて一つのライブラリにするのが大変なんだよ!」と言われそうですし、その通りと思いますが…。