VC6を使用しています。
GetProcessWorkingSetSize関数というのがあるのですが、
この関数は動的メモリを確保する上で、最大と最小の確保容量を決める関数
という認識でよいのでしょうか?(new,malloc等で確保する領域)
この質問とは違いますが、32bitOSでは各プロセス最大2GBまでのメモリを使用
できるようなのですが、アプリのシステム上最大の2GBを必ず確保しないと困る
と言われ、困っていた折に、この関数を勧められたので調べたのですがイマイチ
意味が分からなくて質問しました。
すみませんが、ご協力お願いします。
> この関数は動的メモリを確保する上で、最大と最小の確保容量を決める関数
> という認識でよいのでしょうか?
違います。
メモリには、メモリモジュール(いわゆる PC のメモリ。2GB 搭載とか 4GB 搭載とかい
うアレ)と、HDD 上のスワップファイルがあります(他にもメモリマップドファイルと
かもありますが省略)。
いきなり余談ですが、メモリモジュールのことを「物理メモリ」と呼んで、その対義語
として HDD 上のスワップファイルを「仮想メモリ」と呼ぶことがありますが、これは間
違いです。
物理メモリはともかくとして、仮想メモリはメモリモジュールとスワップファイルの総
称です。
アプリケーションが扱うポインタは、物理メモリを指したりスワップファイルを指した
りします。アプリケーションが、そのどちらを指しているのかを知る必要はありません
し、知ることもできません。
これはつまり、アプリケーションから見てメモリが「仮想化」されているということ
で、「仮想メモリ」とはそういうことです。
しかし、物理メモリとスワップファイルではパフォーマンスに大きな差があるので、時
にはアプリケーションが物理メモリをどれだけ使えるかということが問題になる場合が
あります。
「プロセスのワーキングセット」とは、そのプロセスが(スワップファイルではなく)
物理メモリ上に確保しているメモリサイズのことです。
GetProcessWorkingSetSize で取得できるのは、この最小値と最大値です。
ここで注意すべきは、GetProcessWorkingSetSize が返す値は、あまりアプリケーション
の役には立たないということです。
たとえば、このサイズまでは malloc なり new なりした結果が必ず物理メモリ上に置か
れるかというと、そうとは限りません。
アプリケーションの他の部分で既にワーキングセットを使っているかもしれないからで
す。
> アプリのシステム上最大の2GBを必ず確保しないと困ると言われ
そういう用途の関数ではありません。
また、32bit アプリでは、どうやっても一度に 2GB ぴったりは確保できません。
一度に 2GB 確保する必要があるなら、64bit OS にするしかありません。
「一度に」と書いたのは、何度かに分けて確保、開放すれば、32bit OS でも成功する可
能性があるからです。
これは、
1,何度かに分けて確保
2,処理
3,開放
ではありません。
1,確保
2,処理
3,開放
4,1~3を何度か実行
ということです。
アプリをこのように作りかえられない限り、32bit OS ではどうやっても無理です。
64bit OS でも、物理メモリを 2GB 占有するのは難しいと思います。PC の搭載メモリ
は 64bit マシンでも多くて 4GB 程度で、そのうち 2GB を占有することになるからで
す。
が、64bit OS なら仮想メモリ空間は 32bit OS とは比べ物にならないほど大きいので、
スワップファイルやメモリマップドファイルならほぼ確実に成功するのではないかと思
います。
たとえSetProcessWorkingSetSize()が成功しても
経験上、要求どおりにならないことがほとんどです。
だから使った例もあまり見ません(笑)。
ワーキングメモリの最小値について、
>アプリのシステム上最大の2GBを必ず確保しないと困る
とするなら、そのような設計は間違っています。
なぜなら、当然ですが、Windowsではそんなことはしていないからです。
どうしてもメモリをロックしたいならVirtualAlloc() VirtualLock()
するべきですが、いずれにしてもOSや他のアプリが不安定になる可能性
がありますのでやめたほうが良いと考えます。
結局、Windowsにおいては、固定的で巨大なメモリエリアを常に物理的にキャッシュ
する設計は、OSのポリシーにそぐわないものなのです。
同時に設計者の工夫がやや足りないと非難されても仕方ありません(vv;)。
> アプリのシステム上最大の2GBを必ず確保しないと困る
そんなアホな事を言い出した人に「物理メモリ1GBのマシンでどうするんですか」と
訊いてみる事をお勧めする。
要仕様レベルの再検討、だと思うのだが・・・
> どうしてもメモリをロックしたいならVirtualAlloc() VirtualLock()
> するべきですが、いずれにしてもOSや他のアプリが不安定になる可能性
> がありますのでやめたほうが良いと考えます。
それらを使っても、32bit OS では一度には無理ですし、複数回に分けて確保しても(確
保→確保→確保→処理→開放→開放→開放という方式では)、総量が 2GB に達すること
はありません。
DLL や EXE がマップされている分もユーザーモード空間の 2GB から差し引かれますの
で、動的に確保できる総量は 2GB 未満になります。
> そんなアホな事を言い出した人に「物理メモリ1GBのマシンでどうするんですか」と
> 訊いてみる事をお勧めする。
「だって 2GB 使えるって言ったじゃないか」って言い返された時の対策を用意したうえ
でね。
物理メモリ 1GB のマシンでも動的に 1GB 以上確保できる可能性はあります。
早速の返信有難うございます!
皆さんの丁寧な説明のおかげで、物理メモリや仮想メモリの意味が
少し理解できたと思います。
確かに設計自体に無理があると言えばそうですね、、、
ただ、現状でなんとかしないといけない状況だったので敢えて質問しました。
ところで、皆さんの意見の中でいくつか気になるヒントがあったのですが、
速度やシステムの不安定さを犠牲にしてでもメモリを確保したいといった
場合に、VirtualAlloc()やVirtualLock()が使えそうですね。
もし、スワップファイルとして確保された場合は、データアクセスが遅くなって
しまいそうですが、動作の遅れはシステム上問題ないので、取り合えず
この関数について調べてみようと思います。
有難うございます。
一応、解決チェック入れましたが補足です。
> そんなアホな事を言い出した人に「物理メモリ1GBのマシンでどうするんですか」と
> 訊いてみる事をお勧めする。
PCの要求仕様で、メインメモリ4GBとしているので、
それ以下のPCは対象外にしています。
あと、何故大きいメモリ領域の確保が必要なのかですが、
スキャナから取得したA3サイズの生画像データ(表裏各100MB)を
GPUで加工して、表裏それぞれに3種類(計6画像)出力するのに、
メモリの空き(100MBx6)がどうしても必要だったからです。
この辺の処理は工夫次第で改善できそうですが、アプリとのI/Fが
旧システムと互換なので、改良が難しいのが現状です。
VC6では可能かどうかわかりませんが、
VC2005あたりなら、32ビットOSであっても
AWEを使うことで、2GB以上のデータを同時に物理メモリ上にのせて
ある程度、連続的に扱うことは可能です。
この「ある程度」が曲者ではありますが、HDDに細かく保存しながらよりは早い
>メモリの空き(100MBx6)がどうしても必要だったからです。
100MBごとを、読み込みで2個、加工で6個なら、
32OSでもとくに気にせずとれるはず。
AWE を使おうが何を使おうが、連続した 2GB の仮想アドレス空間が確保できない以上、
できないものはできません。
AWE は、使いようによっては 2GB 以上のデータを同時に物理メモリに乗せることが出来
る技術ですが、同時にアクセスできるのは 2GB 未満になります。
また、特権が厳しいので、ユーザーモードアプリでは通常使わない(使えないことはな
いが、それ専用のマシンでもない限りは向かない)と思います。
で、
> スキャナから取得したA3サイズの生画像データ(表裏各100MB)を
> GPUで加工して、表裏それぞれに3種類(計6画像)出力するのに、
> メモリの空き(100MBx6)がどうしても必要だったからです。
って、800MB あればいいんじゃないですか?
しかも、800MB の連続した空間である必要はない気がします。
うまく作れば、一度に必要なのは 100MB で済みそうな気もします。
まぁ、
> アプリとのI/Fが旧システムと互換なので
っていうあたりがネックになって、「うまく作れる」かどうかわかりませんけどね。
>AWE を使おうが何を使おうが、連続した 2GB の仮想アドレス空間が確保できない以上、
>できないものはできません。
んーと、俺が「何をできる」と書いたと思ってんだろうか?
>また、特権が厳しいので、ユーザーモードアプリでは通常使わない(使えないことはな
>いが、それ専用のマシンでもない限りは向かない)と思います。
逆をいえば、
「顧客側が、自分たちの作業のためにハードの仕様を決め、準備してるような場合」
なら問題はないと思います。
4GBなどの決定してるハード要求事項があり、
スキャナ取り込み・印刷まで行うことも決まってるあたり、
用途専用の可能性は高いと思います。
まぁ推測ですが
> んーと、俺が「何をできる」と書いたと思ってんだろうか?
スレ主が「AWE を使えば一度に 2GB 確保できる」と誤解しないように釘を刺したと御理
解いただければ。
御気分を害されましたら申し訳ありません。
> まぁ推測ですが
うーん…
個人的印象としては、一台限りの専用機というようには見えませんでした。
また、専用機を用意するなら、64bit にするのは難しくないと思います。
たくさんある 32bit PC で実現したいのではないかな、と思います。
推測ですが。
ryoさん、aetosさん 返信ありがとうございます
> 4GBなどの決定してるハード要求事項があり、
> スキャナ取り込み・印刷まで行うことも決まってるあたり、
> 用途専用の可能性は高いと思います。
> たくさんある 32bit PC で実現したいのではないかな、と思います。
↑実際は用途専用になると思いますが、詳細までPCの仕様を決めている
訳ではないです。(GPUとメインメモリぐらいです。)
AWEというのは初めて聞きました。
調べたら「メモリ管理の拡張機能」って説明がありましたが、RAMDISKみたいな
ものでしょうか?
他の作業が入ってしまい、VirtualAlloc()やVirtualLock()もまともに調べて
いない状況でしたので返事もままならず、すみません。
これから自力で調べて、わからない時はまた別のスレッドで質問しようと思います。
マシンに大量の物理メモリが搭載されていても、アドレス空間の制限から、32bit OS で
は同時に 2GB 未満しか使うことができません。
AWE を使うと、同時に 2GB 以上の物理メモリを「確保」することができます。ただし、
アドレス空間の大きさが変わるわけではないので、同時に「使用」できるメモリは依然
として 2GB 未満です。
広大な物理メモリを、2GB 未満という限られた大きさの「窓」を通してのぞく様子をイ
メージしてください。
AWE とは「Address Windowing Extension」の略で、「Window」とは「窓」のことです。
例えば、物理メモリ領域に 10GB を確保し、そのうち 1GB を「窓」を通して使用する。
その 1GB を使い終わったら、また別の 1GB を「窓」を通して使用する。
この場合、「確保」しているのは 10GB ですが、同時に「使用」しているのは 1GB で
す。
「窓」の大きさを 1GB と定めたら、同時に見えるのはその「窓」の大きさまでです。
「確保」はずっとしているので、使用していないメモリ領域の内容も解放されるわけで
はなく、また「窓」を通してのぞけば維持されています。
注意点は、この機能は特定の特権を有効にする必要があるということです。
この特権はデフォルトでは Administrator でも持っておらず、セキュリティ ポリシー
で有効にする必要があります。
また、この機能では必ず物理メモリを確保します。この機能で使用するメモリはページ
ングファイルに退避されません。
そのため、そのアプリ専用のマシンを用意するのでもない限り、他のアプリへのメモリ
の圧迫が著しいものとなりかねません。
必要な特権は System アカウントではデフォルトで有効になっているあたり、サーバー
アプリ(Web サーバーとか DB サーバーとか)向けに用意された機能だと思います。