大容量メモリ
2011年5月7日公開
x86の32bitのアーキテクチャでは、メモリは最大4GBまでしか使えないと言われる。
また、mallocに失敗する例として、下記のようなプログラムを見かける。
void* p = malloc( 0xFFFFFFFF );
if ( NULL == p ) {
printf( "メモリの確保に失敗しました。\n" );
}
|
まぁ確かに、問答無用で4GBのメモリ領域を要求すれば失敗するのも無理ないような気がしないでもない。
だがしかし、俺のマシンには物理的に12GBのメモリが搭載されている。ということは、4GB程度であれば余裕で割り当てられるのではないか?
ということで、ちょっとやってみた。
テスト用のプログラム
わかりやすいように、メモリの確保だけを行うテスト用のプログラムを作ってみた。
画面には、確保されるメモリ領域長を入力するエディットボックスとボタンを配置しておく。

OKをボタンを押下すると、メモリの確保を行い結果を表示する。

プログラムはこうなっている。
void CMemoryTestDlg::OnBnClickedButton1()
{
unsigned int i = 0;
unsigned int j = 0;
unsigned int k = 0;
unsigned int allocsize = 0;
CEdit* p = (CEdit*)GetDlgItem( IDC_EDIT1 );
CString str;
size_t size2 = 0;
// 既存のメモリ領域を開放する
for ( i = 0; i < vBuffer.size(); i++ ) {
free( vBuffer[i] );
vBuffer[i] = NULL;
}
// 入力されたメモリ領域長を取得する
p->GetWindowTextW( str );
size2 = _ttoi( str );
// 512MB単位で確保する個数と余りを算出する
j = size2 / 512;
k = size2 - ( j * 512 );
// 512MB単位でメモリ領域を確保する
for ( i = 0; i < j; i++ ) {
void *p = malloc( 512 * 1024 * 1024 );
if ( NULL == p )
break;
for ( l = 0; l < k * 1024 * 1024; l++ )
( (char*)p )[l] = 0;
vBuffer.push_back( p );
allocsize += 512;
}
// 余りの分を確保する
if ( k > 0 ) {
void *p = malloc( k * 1024 * 1024 );
if ( NULL != p ) {
for ( l = 0; l < k * 1024 * 1024; l++ )
( (char*)p )[l] = 0;
vBuffer.push_back( p );
allocsize += k;
}
}
// 結果を表示しておく
str.Format(
_T( "要求されたサイズ:%u\n確保したサイズ:%u" ),
size2, allocsize
);
MessageBox( str );
}
|
処理内容としてはコメントに記載しているとおり、512MB単位でmallocを行い、最後に余りの分を確保して、結果を表示するというだけである。
たとえば、エディットボックスに「1025」と入力したのであれば、512MBのmallocを2回と、1MBのmallocを1回行うことになる。
64bit版Windows7での動作
動作確認を兼ねて、64bit版Windows7で動かしてみた。
まずは32bit用にコンパイルした場合。


1456MBまでは正しく領域を確保することができるらしい。
64bit用にコンパイルした場合。

たくさん確保できるようだ。
ついでに言うと、タスクマネージャのメモリ使用量の表示が大変なことになる。

限界に挑んでみた。

スラッシングが発生して酷いことになったが、32GBのメモリ領域の確保に成功してしまった。
今度は、32bit版のプロセスを多数起動してみる。

1プロセスあたりの最大は1.4GB程度だが、そのプロセスを多数起動することは可能なようだ。

例のごとく、タスクマネージャの画面は大変なことになっている。
64bitの環境
早速だが、64bitOSでの動作を確認してみた。
なお、動作環境は全てVirtualBoxであり、仮想OSに割り当てるメモリ容量は全て8192MBである。なおかつ、限界値がわかりにくくなるので仮想OSでのページング領域のサイズは0に設定している。
ただし、Windows 7とWindows
Server 2008は仮想環境ではなくホストOSの値を記載している。なぜならば環境を作るのが面倒だったからだ。
| バージョン |
バージョン番号 |
認識されたメモリサイズ |
1プロセスの最大(32bit) |
1プロセスの最大(64bit) |
複数プロセスの最大 |
| Windows XP Professional SP3 |
5.2.3790 |
8.0GB |
1293MB |
7344MB |
7344MB |
| Windows Server 2003 R2 Enterprise Edition |
5.2.3790 |
8.0GB |
1293MB |
7339MB |
7339MB |
| Windows Vista Ultimate |
6.0.6002 |
8.0GB |
1750MB |
7060MB |
7060MB |
| Windows Server 2008 R2 Standerd Edition |
6.1.7600 |
8.0GB |
1700MB |
6244MB |
6244MB |
| Windows 7 Professional(注1) |
6.1.7600 |
12.0GB |
1456MB |
10456MB |
10456MB |
注1 Windows 7は12GBの物理メモリを搭載したマシンで動作した値を記載している。
なお、上記で述べたとおり、ページング領域を0より大きな値にすればその分メモリを使用することができる。複数プロセスで共用して使用することもできるし、1プロセスで目一杯まで使ってしまうこともできる。
32bitの環境
同じ要領で、32bitOSでの動作を確認してみた。
動作環境は同じくVirtualBoxであり、仮想OSには8192MBのメモリを割り当てて起動している。
| バージョン |
バージョン番号 |
認識されたメモリサイズ |
1プロセスの最大 |
複数プロセスでの最大 |
| Windows 98(注1)(注2) |
4.10.1998 |
1160MB |
240MB |
1029MB |
| Windows 2000 Professional SP4(注2) |
5.00.2195 |
3.5GB |
1499MB |
3354MB |
| Windows XP Professional SP3 |
5.1.2600 |
3.5GB |
893MB |
3140MB |
| Windows Home Server SP2 |
5.2.3790 |
4.0GB |
1293MB |
3621MB |
| Windows Server 2003 SP2 Enterprise Edition |
5.2.3790 |
8.0GB |
1293MB |
7682MB |
| Windows Vista Ultimate |
6.0.6002 |
3.5GB |
1657MB |
2796MB |
| Windows 7 Ultimate |
6.1.7600 |
3.5GB |
1657MB |
3028MB |
注1 Windows 98は1160MB以上のメモリを割り当てると正常に起動できなくなる。
注2 Windows 2000およびWindows 98は、Visual Studio 2010のランタイムがインストールできないことから、上記のプログラムと同じ処理を行うものをVisual
Studio 6.0で作り直している。
なお、認識されるメモリ領域が4GBないし3.5GBに制限されていたとしても、ページング領域を必要十分に確保してあげれば、それ以上のメモリ領域(仮想記憶領域)を使用することができる。もっともその場合は、本当は使うことができるはずのRAMが使用されることはなく、ディスクI/Oが多発することになるため性能が著しく劣化することになる。
たとえば下記は、Windows 2000でメモリを8192MB割り当てて起動し、なおかつ合計で4GB以上のメモリを使用してる時の画面である。

使えるRAM領域は3.5GBだが、7.5GB程度の仮想記憶領域が割り当てられていることが分かる。
/3GB指定
32bitOSで32bitのプロセスを実行する場合、使えるメモリの上限が2GBにすら届かないのは、OSが2GBのメモリ空間を使用しているためだという。いろいろと検索したら、こんなページが出てきた。
そのページの記載によれば、C:\BOOT.INIに/3GBという指定を追加してやって、なおかつ、実行ファイルにIMAGE_FILE_LARGE_ADDRESS_AWAREというフラグを設定してやれば、ユーザ領域として3GBまで使えるようになるらしい。
ということでやってみた。
まずは、c:\BOOT.INIを編集する。

折り返し表示になっているが、最後と最後から2番目の行は1行である。でもって、行末に「/3GB」という指定を追記してやった。
次は、実行プログラムの編集である。Microsoftの説明のページではeditbin.exeを使えと記載されていたが、そんなことおwしなくてもVisual
Studio 2010ではリンク時の設定として「/LARGEADDRESSAWARE」が指定できるようになっている。

これで、再コンパイルしてやれば完了である。
その上でもう一度測定してみる。
| バージョン |
認識されたメモリサイズ |
1プロセスの最大 |
| Windows 2000 Professional SP4 |
3.5GB |
1499MB |
| Windows XP Professional SP3 |
3.5GB |
1535MB |
| Windows Server 2003 SP2 Enterprise Edition |
8.0GB |
2047MB |
測定するにはしたが、正直言ってかなり酷いことになる。
「/3GB」のフラグをつけて再起動しただけで、OracleVMのディスプレイドライバが使えなくなり、640x480・16色表示になってしまう。それ以外にもいろいろなプロセスが正常に起動できず、ネットワークへのアクセスもだいぶ疑わしくなる。それでも一応、使えるメモリ領域がちょっとだけ増えた。
なお、Windows VistaとWindows 7はやり方がよく分からなかったし、調べるのも面倒になったからやっていない。
|