multi_index_container - インデックスの型

前回 multi_index_container は
multi_index_container<
  要素の型,
  indexed_by<
    インデックス0の指定,
    ...,
    インデックスNの指定
  >
>
のようなテンプレート引数をもつと書いたが、インデックス部分の指定を詳しく見ていく。

multi_index_container - キーエクストラクタ

multi_index_container のインデックスのタイプが ordered_unique、または ordered_non_unique の場合には、さらにそれらのテンプレート引数にキーエクストラクタが必要となる。キーエクストラクタには大きく、identity, member, const_mem_fun, mem_fun の4種類がある。

multi_index_container - 要素の更新

multi_index_container は各インデックスごとに std::listまたはstd::set、std::multisetとよく似たインターフェースを介して操作が行えるが、大きな違いのある部分の1つが要素の更新方法だ。

メンバ関数単位のフレンドクラスの指定

C++のfriend指定は、自分のクラスの全てのメンバ関数、メンバ変数の無制限アクセスをフレンドクラスに与えてしまう。(自分のすべてを見せて触らせるなんて、普通の感覚ではフレンドよりも深い関係だな...)
これをある特定のメンバ関数のみをフレンドクラスに公開させたいという拡張はすぐ考え付くところだと思う。「C++の設計と進化」を読むと、実際こういった提案は多くだされたらしいが、ストラウストラップは意味がないと提案を突っぱねている。
んが、やはり、メンバ関数単位でフレンドクラスの指定ができたほうがコードの可読性、メンテ性があがる場合があると個人的には思う。

ってことで、現状のC++で無理やりこれが実現できないか考えてみた。

デバイスステート切り替えコスト

仕事が少し落ち着いてきたので、久しぶりにHamana の開発をやった。やりたいことはいくらでもあるのだが、大体月に2日程度しか工数を割り振れないのでなかなか進まない。
まあ仕事と違って、のんびりが許されるから楽しいんだけど。

さて、Hamana で動画再生中にファイルリストとサムネイルウインドウを表示させると妙に重かったのだが、まあテクスチャマップされたポリゴンを大量に描画しているので、こんなものだろうとあまり気に留めていなかった。(文字もサムネイルもすべてテクスチャで描画している)

ところが、今日別件でhamana上で大量のテクスチャマップされたポリゴンを描画させてみたら軽い軽い! つまりサムネイルかファイルリストの描画になんらかの無駄があると判明したので詳しく調べることにした。

で、結局直接の原因はサムネイルの描画が次の処理シーケンスになっていたことだった。
  1. すべてのサムネイルに対して2から5を繰り返す
  2. Direct3Dデバイスの頂点フォーマットをテクスチャなしのものに設定する
  3. サムネイルの枠と背景を描画
  4. Direct3Dデバイスの頂点フォーマットをテクスチャありのものに設定する
  5. サムネイル画像を描画
つまり2,4の頂点フォーマットの切り替えをサムネイル画像ごとに行っていたのがマズかった。

これを次のようにしたらCPUの使用率が80%から10%まで改善した(毎秒60フレームで描画)。
  1. Direct3Dデバイスの頂点フォーマットをテクスチャなしのものに設定する
  2. すべてのサムネイルの枠と背景を描画
  3. Direct3Dデバイスの頂点フォーマットをテクスチャありのものに設定する
  4. すべてのサムネイル画像を描画


描画するサムネイルは高々20個程度のわけなので、これによって節約できる描画ステートの切り替えは40回程度なのだが、まさかここまでパフォーマンスに大きな影響を与えてるとは想像もつかなかった。

<< 3/5 >>