前にVC++の各種配列・配列オブジェクトについて比較してみたが、今回はさらにC++/CLIでのarrayも加えて比較する。ということで、.net frameworkを利用した場合速度がどうなるのか見てく。
プロジェクトプロパティ設定
C++/CLIを使うには、下のようにプロジェクトのプロパティで共通言語ランタイムのサポートで共通言語ランタイム サポート(/clr)を選ぶ必要がある。
この時注意点として、MFCの使用は共有DLLでMFCを使うを選ばなければならない。これは、このプロジェクトのプロパティのC++設定項目のうちコード生成においてランタイム ライブラリをマルチスレッド DLL (/MD)などのDLLタイプを選ばなければならないからである。
配列の宣言
配列の宣言は下記の通り。各配列ごとに128のサイズを確保している。
1 2 3 4 5 6 7 8 9 10 11 12 |
CArray < int > a; a.SetSize( 128 ); CAtlArray < int > b; b.SetCount( 128 ); vector < int > c; c.resize( 128 ); int d[ 128 ]; array < int > ^ e = gcnew array < int > ( 128 ); |
ちなみに、最後のがC++/CLIによる配列生成だが、
1 2 |
array < int > ^ f; array < int >::Resize( f, 128 ); |
このように、2段階でもできる。(Resizeはstaticで宣言されているようなので、fを渡さなくてはならない。)
測定
いつのものようにQueryPerformanceCounterを使って測る。測り方としては、以下のようなテンプレート関数を使う。配列に自分のカウントをコピーし、それを1024*1024回ループしてそのかかった時間を測る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
template < class _TYPE > void MeasureLoop ( _TYPE & v, const int s ) { for( int m = 0; m < 1024 * 1024; m++ ) { for( int n = 0; n < s; n++ ) { v[ n ] = n; } } }; |
なおこの関数を呼ぶ部分は、下の通り。今回の場合配列サイズは128固定なのだが、それぞれなるべく動的に正しい値を渡せる方法で渡してみた。(Lengthはプロパティである)
1 2 3 4 5 |
MeasureLoop( a, a.GetCount() ); MeasureLoop( b, b.GetCount() ); MeasureLoop( c, c.size() ); MeasureLoop( d, sizeof( d ) / sizeof( int ) ); MeasureLoop( e, e->Length ); |
結果
いつものようにIntel Core 2 Duo E6600のマシンで測定してみた。それぞれかかった秒数は、
タイプ | 時間 |
---|---|
CArray | 0.178039 秒 |
CAtlArray | 0.156952 秒 |
vector | 0.230775 秒 |
配列 | 0.071936 秒 |
array | 0.174898 秒 |
ということであった。特にC++/CLIのarrayが劇的に遅いといったことはなかった(むしろvectorより速い)。
ただし、array以外は配列のポインタが取れるのでおそらく配列と同じ速度で動かすことができるが、arrayの場合ポインタが取れないので配列の速度での演算はできない。安全による代償ともいえるが、SSEなどを使う場合には対応できないのではないかと思う(そもそもSSEを使うということなら、わざわざ.netを使う必要性はないか、、、)
また、array以外について共通言語ランタイム サポート(/clr)をはずして実験してみた。
タイプ | 時間 |
---|---|
CArray | 0.177003 秒 |
CAtlArray | 0.147903 秒 |
vector | 0.230864 秒 |
配列 | 0.070194 秒 |
若干ではあるが(誤差かもしれない)速くなった。なお(array部分のコードを取って)メモリ使用量を比較してみると、
タイプ | メモリ使用量 | 仮想メモリ使用量 |
---|---|---|
/CLRあり | 6892 KB | 7904 KB |
/CLRなし | 2024 KB | 612 KB |
というように、メモリ使用量についてはかなり差がでることがわかった(ハンドル数、スレッド数、GDIオブジェクトなども/CLRありの方が大きい)。その他、弱点としてはCLRの場合デバッガが遅いという弱点がある、、、(アプリケーションのユーザーには指して関係ないかもしれない)
ピンバック: VC++ 配列・配列オブジェクトの不正位置参照エラー | 豆知識