- ベストアンサー
続 仮想メモリの制御
昨日 http://oshiete1.goo.ne.jp/qa3665270.html で質問させていただいた者です。 沢山の方に多様なアドバイス頂き感謝しております。 さて当方のメモリ使用量に関しまして、調査したところ、 初めの行列の宣言がメモリを食いまくっていることが発覚しました。 そこでグローバルで ------------------- #define FRAMES 1000 #define WX 640 #define WY 480 int arraya[FRAMES][WX*WY]; --------------- の配列を宣言すると 普通に計算すると1000×640×480×4=約1.2GB になるため、さすがに大きすぎると思い、 ------------------- #define FRAMES 300 #define WX 320 #define WY 240 int arraya[FRAMES][WX*WY]; --------------- 約92.16MBにしても両方とも物理メモリ制限一杯の 1.3GBを消費してしまいます。 これはプログラム自体を実行する以前になってしまうため、 宣言自体に問題があるのかと思うのですが、 何か定義したり、設定したりしなければいけないのか、 もしくは、宣言する場所が不適切なのでしょうか? 開発ツールはVC++です。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
他の回答者の回答など見て回ってましたが、軒並み有効な手段はあがってますね。 どこにはまってるのでしょう。 HDDが遅いというだけなら、メモリ増設や、既に前質問に回答のあったRAMドライブで多分解決です。 大量にメモリに抱き込むという現在の戦術では多分上記がシンプルで最適解なのではないでしょうか。 これも既に出てますが、静止画に落とさずに動画で保存するというのもひとつの手です。 あと、瞬発力云々言ってますが、常に表示しているのでなく、特定の条件下でだけ表示? 場合によっては、バックグランドでVRAMに転送しておく手もありそうです。 グラボも性能がいいやつはメモリも多いし転送も速いです。 いずれにせよ、1GBの走査とかする可能性があると、 読み書きで非同期/スレッド化くらいは必須と思いますが、そのあたりはどうでしょう。
その他の回答 (4)
- MrBan
- ベストアンサー率53% (331/615)
■大規模メモリ確保の弊害。 staticに1GBの配列を取ったプログラムをロードしたとします。 起動時点で、1GB分のメモリが確保されます。(仮想だとしても) そして、全体が同時にメインメモリに乗らないとしても、 static領域の0初期化のため、順次一度はメモリに載るでしょう。 この際に、他のメモリ(大事なものを含む)を押しのけかねない。 (システム全体のパフォーマンスが落ちる) また、メモリキャッシュを利かせることも無視できませんが、 1GBの領域を走査…とかしてる時点で毎回キャッシュ塗り替えますね。 さらに、一見地味ですが、他にもアドレス空間としても実に1GB分の連続領域を要求しますので、 DLLなどが別の場所にロードされることになって、呼び出しが遅くなるとかもあります。 ■メモリの増加について > 1.3GBを消費してしまいます。 どうやって確認していますか。どこのなんという値をみて、増加してるといっていますか。 今まで動的確保の仕方を知らなかったとすると、意図してやってなさそうなので… 増えて本当に問題がある値なのか、問題のない値なのか。 場合によってはメモリ以外のリソースリークとかも怪しいかもしれません。 ■動的確保について array = new int[WX*WY]; // この書き方だと画面1枚分ですが意図通りですか。 *array=0; // array[0] =0;(先頭だけ0)ですが、意図通りですか。 ■設計方針について Windows上のアプリではワーストの速度保証ができないわけで、 Windowsアプリにあまりそぐわない処理で性能を出したがっているようにも思えますが。 ■参考 所詮Windowsでできるメモリ制御はページフォルト抑制レベルです。(参考URL) 大規模な確保は難しいと思いますが、今のような力技でどうしても本当にメモリ確保したいなら、 ワーキングセットとかページとか調べてみてください。メモリ増設前提でいいならアリかもしれません。
- zwi
- ベストアンサー率56% (730/1282)
どんどんメモリが減っていくならmallocやnewを繰り返しているとしか思えません。そこは確認しましたか?
- MrBan
- ベストアンサー率53% (331/615)
特に設定しないとVCでのスタックなんて1MB程度しかないわけで、 無設定でスタックだったら落ちてます。まず動くこと自体がありえない。 よって、staticをつけても変わらないと思われます。 100MB程度ならnewなどで動的に取ればよいのではないでしょうか。 静的に大規模なメモリを取ろうとしているのが他を圧迫してる可能性はあります。 なお、メモリマップドファイルは、質問者さんの目的からすると 結局仮想メモリのスワップアウトと動作原理的に大差ないので、 OSのメモリ管理以上に最適な制御などができないようであれば、 速度的に改善する保証がないと思いますが。(遅くなる可能性も含め)
補足
newを使って動的に宣言してみましたが、症状は変わりません。 というか初の試みのため、宣言の仕方が正しくない恐れがあります。 ----------------- void Main(void) { int *array; array = new int[WX*WY]; *array=0; for(;;){ メインの処理 } Printf("Stop\n"); delete [] array; ----------------- 確かにメモリアップドファイルを使う場合、私の持っているHDD だと転送レートが小さいため、最終的な目的は達成できません。 そのため、こちらをトライするのは後々にして、 とりあえずメモリが膨張している原因を知りたいです。 >静的に大規模なメモリを取ろうとしているのが他を圧迫してる可能性はあ>ります。 大規模なメモリをとると、どういう現象が起こり、 具体的にはどう圧迫しているのでしょうか?
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス ・配列に『static』キーワードを付けてみたらどうなりますか? 原因は良く分かりませんが、勝手に推測するとスタック上のメモリに巨大なバッファを 確保していて再帰的に呼ばれているかもしれない。と考えるとどんどん増えるのが説明 付きそうな? ・とにかく調べてみて下さい。 (1)巨大な配列はグローバルで定義したり、static キーワードを付けてみて下さい。 (2)あるいは malloc、calloc、new などで動的に確保して既に確保済みならエラーを出すとか。 (3)前回紹介したメモリ・マップド・ファイルは使わない方針ですか? ・以上。参考に。
補足
ありがとうございます。 症状としてはおっしゃる通りメモリがどんどん増えている様子で、 仮想メモリは使わないように設定しておりますので、 終いには動かなくなってきてしまいます。 ご紹介いただきました、メモリ・マップド・ファイルは まだトライしておりません。 むしろ、宣言しているメモリ量よりはるかに大きな メモリが食われている様子ですので、こちらを解決したく。 既にグローバルで定義しており、 staticをつけても変わりありませんでした。 (2)の動的な処置からのチェックをしてみようかと思います。
お礼
ありがとうございます。 勉強不足であり、より調査が必要みたいです。 メモリの管理はタスクマネージャーで見ていました。 プログラムを起動するとすぐに制限メモリ一杯になるので、 どこかおかしいと判断しておりました。 ワーキングセット、是非参考にさせていただきます。