« C++Builder 2007 Update 2 | メイン | アルファブレンドを計る »

2007年08月18日

グラフィックライブラリ:: テンプレートのインライン展開と最適化

    

※ 2007/10/12 追記 : C++ Builder 2007 でも、Update 3 をあてることで以下のコードでも最適化され期待通り動くようになった。

関数オブジェクトを用いて画像のコピーを行う場合、テンプレートがインライン展開され、さらに最適化がかかって高速にコピーされることを期待していた。
が、C++ Builder 2007 でコンパイルとしたところ期待よりも1.5倍ぐらい遅いと言う結果になった。
以下、ソースコードの一部を抜粋。

template<typename T>
struct CPredicate : public std::binary_function<T,T,bool>
{
  inline bool __fastcall operator()( T d, T s ) { return true; }
};
template<typename T>
struct CFunctor : public std::binary_function<T,T,T>
{
  inline T __fastcall operator()( T d, T s ) { return s; }
};
// 以下コピーしている部分のみ抜粋。m は CPredicate で func は CFunctor
for( int dy = d_rect.top, sy = s_rect.top; dy < d_rect.bottom; ++dy, ++sy )
{
  const DWORD* src_pix = &(src_img[sy][s_rect.left]);
  DWORD* dest_pix = &(dest_img[dy][d_rect.left]);
  for( int x = 0; x < dest_w; ++x, ++dest_pix, ++src_pix )
  {
    if( m( *dest_pix, *src_pix ) )
      *dest_pix = func( *dest_pix, *src_pix );
  }
}

上記のようなコードで、CPredicate と CFunctor が使われた場合、ループの中は以下のようなコードと同じになることを期待した。

const DWORD* src_pix = &(src_img[sy][s_rect.left]);
DWORD* dest_pix = &(dest_img[dy][d_rect.left]);
for( int x = 0; x < dest_w; ++x, ++dest_pix, ++src_pix )
{
  *dest_pix = *src_pix;
}

が、800*600の32bit colorの画像5枚を10回コピーした結果を見ると 189 msecぐらいで、下の関数オブジェクトを使用しない版では、112 msecぐらいだった。
これは困る。
上のコードの結果は両方同じになってくれることを期待して作っているのに。

でも、これは C++ Builder 2007 の最適化が弱いだけかもしれないと Visual C++ 2005 で同じものをビルドしたところ、両方 112 msec ぐらいになった。
なんだ。
良かった。
C++ Builder 2007 では遅くなってしまうが、VC では問題ないようだ。
ついでに MinGW でも試したところ、VC と同じような結果になった。
C++ Builder 2007 が期待よりも遅いだけのようだ。

ツールの画像コピー周りの処理は VC で DLL を作って Builder から呼び出すような形の方がいいかもしれない。



投稿者 Takenori : 2007年08月18日 18:25




comments powered by Disqus
Total : Today : Yesterday : なかのひと