2017年1月15日日曜日

メモ:C#で2GB以上のメモリ

* 追記:2017/01/17
あとで読み返したら数字とかいろいろおかしいね。やっぱ夜中に文章とか書くもんじゃない。以下参考程度に。
* ここまで


64bitビルドで、例えば構造体配列とかで全体が2GBを超えたい時に使うオプション。

<gcAllowVeryLargeObjects> Element

hoge.exe.configでconfiguration > runtimeにgcAllowVeryLargeObjects enabled="true"を追加する。

ただあんまり使い勝手は良くない気がする。


このオプションを追加した状態では、配列の最大長はUInt32.MaxValue(0x7FEFFFFF)まで、ただし任意の単一次元の最大は0x7FFFFFC7か0x7FEFFFFFに制限される、となる。
つまり、1次元配列の場合は0x7FFFFFC7くらいまで、多次元配列ならすべての要素数がUInt32.MaxValue未満まで、ということになるらしい。

例えば、new int[0x7FEFFFFF/2, 4]という配列は合計長が0xFFDFFFFCでMaxValueを下回っているために作成できるが、new int[0x7FEFFFFF/2, 5]だと合計長が0x13FD7FFFBとなり、作成することができない。

new int[UInt32.MaxValue]という配列を作ることはできない。これは「任意の単一次元は0x7FFFFFC7か0x7FEFFFFFに制限される」という点に引っかかるため。


この合計数は多次元配列にのみ課される制約であり、ジャグ配列には適用されない(多次元配列は[2,3]のタイプ、ジャグ配列は[2][3]のタイプ)。
int[][] arr = new int[0x7FEFFFFF][4];のような大きさだと合計は0x1FFBFFFFCになるが、問題なく作成できる。


前述のとおり、制限になるのは添字だけであり、配列を用意するためのメモリに制限はない。多次元配列ではUInt32.MaxValueが1つの制限となるが、ジャグ配列を使えば回避することができるし、構造体の配列であれば事実上無制限に大きなテーブルを作ることもできる。
とはいえ、実際に使用できるのはPCに実装してある容量の半分前後が目安となる。
僕のデスクトップPCは32GBのメモリを載せているが、使用するメモリが20GBを超えたあたりで実メモリのデータを仮想メモリ(ハードディスク)へ退避し始め、OSのパフォーマンスが極めて低下した。これはブラウザのスクロールがカクつくというレベルではなく、マウスを動かすこともできないレベルのパフォーマンス低下を引き起こす。


ということで、64bitOSで20GBくらいのメモリを専有するプログラムを作る方法はわかった。が、本来の目的である超高解像度Bitmapは結局無理っぽい感じ。いろいろ数字をこねくり回すと前述の数字に近いところが出てくるが、なんか腑に落ちない。とりあえずSystem.Drawing.Bitmapでは前回のエントリで書いた解像度の制限が消えることはないはず。

***

標高データのタイルを貼り合わせるのもだいたいやり尽くした感があるし、そろそろ違う何かで遊びたいなー。何ヶ月単位でやってない電子工作を久しぶりにやりたいところだけど、それには机の周り片付けるところから始めないといけないから、なかなか腰が上がらない。入手性が良くて安くてバカでも使える簡単なArduino非互換な.NetMFボードとかどっかにないかなー。


/*
気が付かなかったけど、これ書いてる途中にFalcon-9の打ち上げがあったのね。惜しいことしたなー。数日中に軌道要素が出ると思うので、次のネタは10機まとめて打ち上げられたイリジウムとTRICOMのTLEを貼り付けるだけの簡単な感じにできるかなー。さすがにSS-520の打ち上げまでには起きられない気がするので、そっちも含めてあとでアーカイブ見ようっと。
*/

0 件のコメント:

コメントを投稿