vectorによって動的に作成されたオブジェクトの描画

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
iguana

vectorによって動的に作成されたオブジェクトの描画

#1

投稿記事 by iguana » 10年前

ローグライクゲームを作っています。
C++のvectorを使ってアイテムのクラスを動的に生成、イテレータを使って内部の描画関数を呼び出して描画しているのですが、
描画時に何故か時間がかかります。
newを使用してリスト構造を組み、同じように描画した時では、100個ほど生成、描画しても動作が重くならなかったのですが、
vectorを使用すると10個足らずで重くなってしまいます。
都合上vectorを使って作成したいと考えています。
もし解決法を知っていらっしゃる方がおりましたらぜひご教授お願いします。

以下描画部分のみのソース

コード:

static void Draw(){
	VcItem::iterator ItemIterator;


	for (int i = -1; i < DrawMapChipNumY; i++){
		for (int j = -1; j < DrawMapChipNumX; j++){
                        //画面内にあるものだけを描画
			if (j + DrawPointX < 0 || i + DrawPointY < 0 ||
				j + DrawPointX >= MAP_WIDTH || i + DrawPointY >= MAP_HEIGHT) continue;
             //MapDraw
			/*マップチップの描画*/


			ItemIterator = vcItem.begin();
			while (ItemIterator != vcItem.end()){
				//アイテムの描画関数を呼び出し
                ItemIterator->Draw(i, j);

				ItemIterator++;
			}
			

		}
	}
}

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#2

投稿記事 by iguana » 10年前

追記
VcItem, vcItem

typedef vector<Item> VcItem;
VcItem vcItem;
で定義されています
Itemはアイテムの座標、描画関数などの要素を含むクラスです

かずま

Re: vectorによって動的に作成されたオブジェクトの描画

#3

投稿記事 by かずま » 10年前

動作が重くなったとという質問なら、
具体的な数値の提示が必要だと思います。

sizeof(Item) はいくつですか?
DrawMapChipNumX と DrawMapChipNumY はいくつですか?

生成は、
Item *p = new Item; vcItem.push_back(*p);
のようなものですか?

vcItem.size() が 10 ということですか?
生成にかかる時間は何ミリ秒ですか?
Draw() の実行時間は何ミリ秒ですか?
Item.Draw(i, j) が呼び出される回数は、
DrawMapChipNumX * DrawMapChipNumY * vcItem.size()
ということですよね。

生成と描画を繰り返しているということはありませんか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: vectorによって動的に作成されたオブジェクトの描画

#4

投稿記事 by softya(ソフト屋) » 10年前

MAP_WIDTH * MAP_HEIGHT * vcItem.size() 回はvcItemのDrawメソッドを呼ぶと思いますが、多すぎたりはしないのでしょうか? 無駄に感じるのですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#5

投稿記事 by iguana » 10年前

情報不足でした申し訳ありません。
数値を示します。

//クラスItemの大きさ
sizeof(Item) : 20byte
//描画するマップチップの数
DrawMapChipNumX : 13
DrawMapChipNumY : 10

//生成

コード:

iGenerateNum = 10;

for (int i = 0; i < iGenerateNum; i++){
	vcItem.push_back(Item());
}
生成、描画にかかる時間は計測していませんが、
生成は一瞬で終わるため問題ありません。
また生成を100個ほどしても、描画さえしなければゲームが重くなることはないので生成は問題ありません。

呼び出される回数は仰るとおりです。
i, jとアイテムのX, Y座標が一致した場合に描画されます。
生成、描画は状態遷移プログラムにて場所がわかれているので繰り返されているということはありません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: vectorによって動的に作成されたオブジェクトの描画

#6

投稿記事 by softya(ソフト屋) » 10年前

iguanaさんの思い込み・勘違い等が、このコードだけでは検証できません。
つまり、こちらでは確認しようがないので、iguanaさんに時間を実測してもらうしか方法がないようです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: vectorによって動的に作成されたオブジェクトの描画

#7

投稿記事 by へにっくす » 10年前

iguana さんが書きました:生成、描画にかかる時間は計測していませんが、
生成は一瞬で終わるため問題ありません。
かずまさんが、具体的な計測値を出して、とレスしているのに、見当はずれな回答をしてますね。
仕事であれば、「じゃ勝手にすれば」と干されますよ。
時間の計測ってどうやるの?と聞けばまだいいんですけどね。

それぞれ怪しいと思う箇所の最初と最後にGetTickCount関数でもかましておいて、その差分を出してみてはどうでしょう?

コード:

int tmp = GetTickCount(); // 開始チックを保持
for (int i = 0; i < iGenerateNum; i++){
    vcItem.push_back(Item());
}
printf("生成:%d", GetTickCount() - tmp); // かかった時間を表示(msec単位)
written by へにっくす

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#8

投稿記事 by iguana » 10年前

見当違いな解答申し訳ありませんでした

描画に関しては、
10体生成時 : 16ms
100体生成時 : 47ms

でした。


生成に関しては、精度が悪いのか
両方の場合で0と表示されてしまいました。
もっと正確に測定する方法はあるのでしょうか?

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: vectorによって動的に作成されたオブジェクトの描画

#9

投稿記事 by へにっくす » 10年前

iguana さんが書きました:描画に関しては、
10体生成時 : 16ms
100体生成時 : 47ms
では、newした場合と、vectorを使った場合とで計測してみてください。
iguana さんが書きました:生成に関しては、精度が悪いのか
両方の場合で0と表示されてしまいました。
もっと正確に測定する方法はあるのでしょうか?
いえ、ふつうはそこまで精度を上げることはしません。
時間がかかるところを特定したいのですよね?
その意味では、生成に関しては問題なさそうですね。
まあ生成に関する時間を調べたいのであれば、
たくさん生成してみて、その総合時間で一つ当たりの生成時間を割り出す方法が使えます。
written by へにっくす

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#10

投稿記事 by iguana » 10年前

先ほど上げた数値がvectorを使った時の数値です。

newを使った場合の描画は
10個生成時、100個生成時ともに、ごくたまに5, 6の文字がちらつくものの基本的に0から変動しませんでした。

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: vectorによって動的に作成されたオブジェクトの描画

#11

投稿記事 by へにっくす » 10年前

iguana さんが書きました:先ほど上げた数値がvectorを使った時の数値です。

newを使った場合の描画は
10個生成時、100個生成時ともに、ごくたまに5, 6の文字がちらつくものの基本的に0から変動しませんでした。
んーそうですか。
もしかして1秒(=1000msec)以上かかるってことではない、ということでよろしい?
(個人的には問題ないと思ってるんですけどね)
目に見えて遅いということでしたら、その根拠を示してほしいですね。

【編集】書きなおしてたら、すでにレスされていたので元の文面に戻しました。
最後に編集したユーザー へにっくす on 2014年3月30日(日) 17:21 [ 編集 2 回目 ]
written by へにっくす

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#12

投稿記事 by iguana » 10年前

目に見えて遅くなりますね。
フレームレートを表示させると、20~30前後の値になります。

個人的に考える原因としては、イテレータを進める処理がnew使用時のポインタを進める処理より時間がかかっているということ、です。
描画回数を減らす新たなループを考えついたので、一応解決とさせていただきます。

ご回答くださった皆さん、大変有難うございました。

たいちう
記事: 418
登録日時: 13年前

Re: vectorによって動的に作成されたオブジェクトの描画

#13

投稿記事 by たいちう » 10年前

コンパイラは何を使っていますか?
コンパイルオプションは?
特に速度に関する最適化について。

例えばVC++のデバッグモードとかだと、デバッグ用に色々とチェックが入り、
newだと一瞬で、vectorだと数10ミリ秒とか、ありえるかと。
その場合、最終的には最適化してコンパイルすれば問題ないですよね?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: vectorによって動的に作成されたオブジェクトの描画

#14

投稿記事 by softya(ソフト屋) » 10年前

たいちう さんが書きました:コンパイラは何を使っていますか?
コンパイルオプションは?
特に速度に関する最適化について。

例えばVC++のデバッグモードとかだと、デバッグ用に色々とチェックが入り、
newだと一瞬で、vectorだと数10ミリ秒とか、ありえるかと。
その場合、最終的には最適化してコンパイルすれば問題ないですよね?
それにしても遅く感じるので、iguanaさんがなにかミスをしている可能性は捨て切れません。
コードを提示してもらえない以上は、ご自身で解決するしか無いわけですが、Drawを除いて計測していないのでイテレータが遅いと断言したのが本当であるか疑問が残る所です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: vectorによって動的に作成されたオブジェクトの描画

#15

投稿記事 by へにっくす » 10年前

iguana さんが書きました:目に見えて遅くなりますね。
フレームレートを表示させると、20~30前後の値になります。
問題ないと書きましたが、
60fpsでやろうとするなら、1000/60=16.7msecなので、やっぱ問題アリです。
10体生成時の描画で16msなのですから。
Draw関数の内容を掲示した方がいいですよ。
(newとvectorしたときのそれぞれのDraw関数に差分がないのであれば、その旨書いてほしかったですね)
written by へにっくす

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#16

投稿記事 by iguana » 10年前

コンパイラはvisual studio 2013で環境も特にいじっていないので初期設定かと。

コンパイルオプションとはどのように設定するものなのでしょうか

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#17

投稿記事 by iguana » 10年前

Draw関数につきまして、
非常に効率の悪い書き方をしていたため、
新しく考えたループに書き換えたところ100個生成しても問題なく動作するようになりました。

改めて、ご協力くださった方々本当に感謝を申し上げます。

たいちう
記事: 418
登録日時: 13年前

Re: vectorによって動的に作成されたオブジェクトの描画

#18

投稿記事 by たいちう » 10年前

> コンパイラはvisual studio 2013で環境も特にいじっていないので初期設定かと。
>
> コンパイルオプションとはどのように設定するものなのでしょうか

2013は使ったことないけど、多分プロジェクトのプロパティで細かく設定できます。
大雑把な設定のまとめが、デバッグモードとリリースモードなのですが、
その違いを知らなくて、初期設定のままならデバッグモードなのでしょう。

デバッグ時に有用な情報を提供してくれる替わりに、実行速度などが犠牲になっています。
速い遅いの話をするときに、デバッグモードでは見当違いなのです。
2つのモードのボトルネックの場所が違う場合も多いので。

ちなみに私の手元のVC2008の場合は、メニューの「ビルド」の「構成マネージャ」で、
「アクティブソリューション構成」で切り替えることで変更できます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: vectorによって動的に作成されたオブジェクトの描画

#19

投稿記事 by softya(ソフト屋) » 10年前

同じような問題に悩んだ人のために、イテレータの回数が問題であったのか、それともDraw中のループなどが問題であったのかだけははっきり記載して頂けますか。

>非常に効率の悪い書き方をしていたため、
ここをもう少し細かくお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

iguana

Re: vectorによって動的に作成されたオブジェクトの描画

#20

投稿記事 by iguana » 10年前

なぜnewと同じ構文で遅延が発生したのかは不明です。

最初におっしゃられたように、
MAP_WIDTH * MAP_HEIGHT * vcItem.size()回のループを回していたものを、
描画関数内に描画場所を直接書き込む事により
vcItem.size()回だけで良くなりました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: vectorによって動的に作成されたオブジェクトの描画

#21

投稿記事 by softya(ソフト屋) » 10年前

iguana さんが書きました:なぜnewと同じ構文で遅延が発生したのかは不明です。

最初におっしゃられたように、
MAP_WIDTH * MAP_HEIGHT * vcItem.size()回のループを回していたものを、
描画関数内に描画場所を直接書き込む事により
vcItem.size()回だけで良くなりました。
無駄を無くしたので、解決したということですね。
イテレータの問題であると言う話はどうなったのでしょうか?
返答で分かることはループが13*10*100回=13000回から100回になったら余裕で間に合うようになったと言うことです。
イテレータなのかDraw側なのか、あるいは両方なのかは不明のままって事ですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る