2011/05/30

vectorの要素数上限とか

作ってるゲームとは関係ないのだけど、
色情報と三次元座標情報を持つたくさんの点を管理する、
というプログラムが必要になったのです。

そこで最近C++のSTLを色々調べていたところなので、
その(個人的)ブームに乗ってSTLのvectorを使ってみたらどうかなーと思ってたところ…。

vectorは要素数が数万くらいになるとデータ構造がぶっ壊れる

みたいな話を聞いて、
うわーマジか数十万は点データ突っ込む予定なのに…と思いつつ
ちょっと本当なのか検証してみました。

以下はそのときのソースコードです。
新しく導入したSyntaxHighlighterを試す意味でも。
#include 
#include 
#include 

using namespace std;

// 点データ(RGBA, 三次元座標)
struct DATA {
 unsigned char r;
 unsigned char g;
 unsigned char b;
 unsigned char a;
 float x;
 float y;
 float z;

 DATA(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a,
  float _x, float _y, float _z) 
  : r(_r), g(_g), b(_b), a(_a), x(_x), y(_y), z(_z)
 {}
};


// メイン
int main( int argc, char **argv ) {
 // リスト作成
 vector dataList;
 dataList.reserve(1000000);

 // 処理時間計測用
 LARGE_INTEGER nFreq, nBefore, nAfter;
 memset(&nFreq,   0x00, sizeof nFreq);
 memset(&nBefore, 0x00, sizeof nBefore);
 memset(&nAfter,  0x00, sizeof nAfter);
 DWORD dwTime = 0;

 float countF = 0.0f;
 int count = 0;

 QueryPerformanceFrequency(&nFreq);
 QueryPerformanceCounter(&nBefore);
 while (1) {
  try {
   DATA data(0, 0, 0, 0, countF, countF, countF);
   dataList.push_back(data);  // データ追加
   count++;
   countF++;
   if (count % (640 * 480) == 0) {
    QueryPerformanceCounter(&nAfter);
    dwTime = 
     (DWORD)((nAfter.QuadPart - nBefore.QuadPart) * 1000 / nFreq.QuadPart);
    // データの入ってる要素数とメモリ確保してる要素数
    cout << "dataList.size: " << dataList.size() 
     << "  dataList.capacity: " << dataList.capacity() << endl;
    // データ追加(640 * 480 コ)にかかった時間
    cout << dwTime << "ms.\n";
    char c[2];
    cin >> c;
    if (c[0] == 'z')
     break;
    QueryPerformanceCounter(&nBefore);
   }
  }
  catch (...) {
   cout << "error!\n";
   return -1;
  }
 }

 for (size_t i = 0; i < dataList.size(); i += 1000) {
  cout << (int)dataList[i].r << ", " << (int)dataList[i].g << ", " 
   << (int)dataList[i].b << ", " << (int)dataList[i].a << endl;
  cout << dataList[i].x << ", " << dataList[i].y << ", " << dataList[i].z << endl;
 }

 dataList.clear();
 cout << "dataList.size: " << dataList.size() 
  << "  dataList.capacity: " << dataList.capacity() << endl;
 
 int n;
 cin >> n;
 
 return 0;
}
環境はCPU: 2.27GHz, メモリ4GB, Windows7, VC++2008使用。
結局これで100万個程度要素を追加してみましたが、
データが壊れるということは起こっていないっぽい…。

要素数というよりは、データの大きさが関係しているのかもしれない。
ひとつの点データは1×4+4×3=16バイト。
それが100万個だと16MBか。
メモリは4GBあるので、それを思うとたいした量ではなさそう。


あと要素の追加にどれくらい時間がかかるのかと思って、計測してみました。
処理時間計測の仕方に関しては処理時間の取得方法の記事を参考にさせていただきました。

640×480個のデータ追加の10回平均が167ms。(Debugモードで)
最初にreserveしてなかったらもっとかかる。
メモリcapacityの拡大も一緒だと300msくらいだった。

ついでに同じことをvectorの代わりに配列を使ってやると約14msでやってくれた。
うむーやっぱり早さでは配列が勝るのか…。


結局わかったことは、

・要素数数万でvectorが壊れるということはなさそう(データの大きさによるとは思うが)
・要素数の上限がわかってるなら配列を使ったほうが良い。早い。

ですかなー。
ちなみにコンパイルをReleaseモードでやるとまたみちがえるほど早くなったのでござる。



0 件のコメント:

コメントを投稿