細かな単位で OpenGL の頂点バッファをたくさん確保していたらこんなエラーに出会いました。ちなみにプログラムの実行タイミング次第では OpenGL で OUT_OF_MEMORY のエラー状態がちゃんと返りました。エラー返す前に異常系に落ちたという感じでしょうか。
この症状が出るまでの様子を、使用システムメモリ、使用VRAM量、使用中の共有ビデオメモリ量、との値をグラフにしてみたものが以下となります。
実験プログラムについて
Windows 7 x64 (16GB) の環境で、 Geforce GTX750 Ti (2GB) を装着しています。
300 描画フレーム間隔で、 128MB の単位で頂点バッファを確保するプログラムを動作させています。また、確保後は次のフレーム以降、バッファ先頭だけ使ってではありますが描画処理も行っています。
このようにしている背景としては、描画されないデータは処理されないのでは?という点と SwapBuffers が呼ばれない場合、作業メモリが解放されないのではという疑惑があるためです。そのために、描画ループを回しつつ、定期間隔で確保実験するに至りました。
この結果について
実際の搭載 VRAM 量までは順調に VRAM 側にリソースが確保されるようです。それがいっぱいになると共有メモリを使うようになっていくのが見えます。このとき、ドライバのなかでデータの整理が行われるのか、一時的に逆転送など行い共有メモリ量が増加&VRAM側をパージしている様子がうかがえました。
また VRAM に確保されようが、システム全体の使用メモリは増加していくのがわかります(黒線のグラフ)。使用した VRAM リソースの合計は約3GBでした。
実験その後
VRAM の断片化とかあるかなと考えて、バッファのサイズを 32MB に減らして再実験しました。このときアプリケーションもまた 32bit ですが、 LargeAddressAware をオンにして 4GB までのアドレス空間使えるようにしてみました。
しかしながら、4GB まで使えるようになったというような結果を予想していましたが、3GB付近でエラーとなってしまいました。アプリケーションのアドレス空間の問題ではないようです。エラーが出た際のプロセスの状況を探ってみると、 1.3GB 程度のメモリ使用量となっており、このときプライベートヒープで割としめられていました。そのブロック単位も 32MB ほどなっており、どうやら VRAM リソースとして確保した何かのコピー(もしくは実体の待避?)かと思われます。これらの情報は VMMap を見れば詳細にわかります。
このような状況になってもちゃんと動き続ける今の Windows や NVIDIA のドライバはすごいなぁと関心もした次第です。
コメント