私は大きな3dスパース配列構造をメモリに無駄なくメモリに保持する方法を探しています。ここで私は、long型の配列を用いた実験を行ってきた:大きな配列はどのようにメモリを割り当てますか?
using System;
using System.Diagnostics;
using System.Runtime;
namespace ConsoleApp4
{
public class Program
{
static Process proc = Process.GetCurrentProcess();
const int MB = 1024 * 1024;
const int IMAX = 5;
const int JMAX = 100000000;
public static void ShowTextWithMemAlloc(string text)
{
proc.Refresh();
Console.WriteLine($"{text,-30}WS64:{proc.WorkingSet64/MB,5}MB PMS64:{proc.PrivateMemorySize64/MB,5}MB");
Console.ReadKey();
}
public static void Main(string[] args)
{
Console.Write(" ");
ShowTextWithMemAlloc("Start.");
long[] lArray = new long[IMAX * JMAX];
long[] l1Array = new long[IMAX * JMAX];
long[] l2Array = new long[IMAX * JMAX];
long[] l3Array = new long[IMAX * JMAX];
ShowTextWithMemAlloc("Arrays created.");
lArray[IMAX * JMAX - 1] = 5000;
l1Array[IMAX * JMAX - 1] = 5000;
l2Array[IMAX * JMAX - 1] = 5000;
l3Array[IMAX * JMAX - 1] = 5000;
ShowTextWithMemAlloc("Last elements accessed.");
for (var i=IMAX-1; i>= 0; i--)
{
for (var j=0; j<JMAX; j++)
{
lArray[i * JMAX + j] = i * JMAX + j;
}
ShowTextWithMemAlloc($"Value for row {i} assigned.");
}
//lArray = new long[5];
//l1Array = null;
//l2Array = null;
//l3Array = null;
//GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
//GC.Collect();
//ShowTextWithMemAlloc($"GC.Collect done.");
ShowTextWithMemAlloc("Stop.");
}
}
}
テストしたい場合は、COMPlus_gcAllowVeryLargeObjects環境変数を設定 - 1に(プロジェクトのプロパティ]> [デバッグ)またはJMAXを変更します。そして、これが出力されます。
Start. WS64: 14MB PMS64: 8MB
Arrays created. WS64: 15MB PMS64:15360MB
Last elements accessed. WS64: 15MB PMS64:15360MB
Value for row 4 assigned. WS64: 779MB PMS64:15360MB
Value for row 3 assigned. WS64: 1542MB PMS64:15360MB
Value for row 2 assigned. WS64: 2305MB PMS64:15361MB
Value for row 1 assigned. WS64: 3069MB PMS64:15361MB
Value for row 0 assigned. WS64: 3832MB PMS64:15362MB
Stop. WS64: 3844MB PMS64:15325MB
私はタスクマネージャでメモリ消費を参照してくださいProcess.WorkingSet64でこのようなものです。実数は何ですか?割り当てにメモリが割り当てられるのはなぜですか?配列は実際に連続して割り当てられたメモリですか?配列は配列ですか?エイリアンは存在しますか? (劇的なバックグラウンドミュージック)
エピソード2:
//lArray[i * JMAX + j] = i * JMAX + j;
var x= lArray[i * JMAX + j];
と何も変化(出力中): 私たちは、小さな変更を加えます。存在と非存在の違いはどこですか? (より劇的なバックグラウンドミュージック)今、私たちは神秘的な人々のひとり(彼らの名前の下にいくつかの数字と小さな「k」がある)からの答えを待っている。つのアレイ(15369から8)/ 4 = 3840メガバイト これは疎な配列ではなく、一部のため
Start. WS64: 14MB PMS64: 8MB
Arrays created. WS64: 15MB PMS64:15369MB
20000000 values assigned. WS64: 168MB PMS64:15369MB
Stop. WS64: 168MB PMS64:15369MB
PMS64:
エピソード3: 別の変更:
//lArray[IMAX * JMAX - 1] = 5000;
//l1Array[IMAX * JMAX - 1] = 5000;
//l2Array[IMAX * JMAX - 1] = 5000;
//l3Array[IMAX * JMAX - 1] = 5000;
//ShowTextWithMemAlloc("Last elements accessed.");
long newIMAX = IMAX-3;
long newJMAX = JMAX/10;
for (var i=0; i<newIMAX; i++)
{
for (var j=0; j<newJMAX; j++)
{
lArray[i * newJMAX + j] = i * newJMAX + j;
//var x= lArray[i * JMAX + j];
}
//ShowTextWithMemAlloc($"Value for row {i} assigned.");
}
ShowTextWithMemAlloc($"{newIMAX*newJMAX} values assigned.");
出力私はこの168MBをフルに使っています。
「なぜあなたは正確なサイズを使用しませんか?」という質問に答えます。私はそれを知らないので?データは、複数のユーザー定義SQLから取得できます。なぜサイズを変更しないのですか? " Resizeは新しい配列を作成し、値をコピーします。これはコピー、記憶の時間であり、最終的に悪いGCが来てあなたを食べる。
メモリを浪費しましたか? (私は覚えていない。宇宙人?!) そして、はい、どのくらい? 0、(3840-168)MBまたは(15369-8-168)MB?
エピローグ:
コメントはコメントか回答ですか?
は実際に連続したメモリですか?
答えが答えますか?神秘的な。 (more music)
(スカリー:モルダー、ヒキガエルはちょうど空から落ち モルダー:!。私は彼らのパラシュートが開かなかったと思います)
はあなたのすべてをありがとう!
*配列は実際に連続して割り当てられたメモリですか?配列は配列ですか?宇宙人は存在するのですか?*はい。はい。おそらく、彼らは遠くにいる*。 –
あなたが逃したかもしれない(実際に面白い)質問は、「メモリは実際にメモリですか?」と疑います。 ...そしてたぶん「大丈夫ですが、メモリがメモリの場合、連続したメモリは実際に連続したメモリですか?」 - いいえ、答えを書くのにこれについて十分なことは分かりません。 – moreON