Seperti yang mungkin Anda ketahui, masalahnya adalah Anda mencoba mengalokasikan satu blok memori yang berdekatan, yang tidak berfungsi karena fragmentasi memori. Jika saya perlu melakukan apa yang Anda lakukan, saya akan melakukan hal berikut:
int sizeA = 10000,
sizeB = 10000;
double sizeInMegabytes = (sizeA * sizeB * 8.0) / 1024.0 / 1024.0;
double[][] randomNumbers = new double[sizeA][];
for (int i = 0; i < randomNumbers.Length; i++)
{
randomNumbers[i] = new double[sizeB];
}
Kemudian, untuk mendapatkan indeks tertentu yang akan Anda gunakan randomNumbers[i / sizeB][i % sizeB]
.
Pilihan lain jika Anda selalu mengakses nilai secara berurutan mungkin menggunakan konstruktor kelebihan beban untuk menentukan seed. Dengan cara ini Anda akan mendapatkan nomor semi acak (seperti DateTime.Now.Ticks
) menyimpannya dalam variabel, lalu kapan pun Anda mulai menelusuri daftar, Anda akan membuat instance Random baru menggunakan seed asli:
private static int randSeed = (int)DateTime.Now.Ticks;
private static Random GetNewRandomIterator()
{
return new Random(randSeed);
}
Penting untuk dicatat bahwa meskipun blog yang ditautkan dalam jawaban Fredrik Mörk menunjukkan bahwa masalah tersebut biasanya disebabkan oleh kurangnya ruang alamat , blog tersebut tidak mencantumkan sejumlah masalah lain, seperti batasan ukuran objek CLR 2GB (disebutkan dalam komentar dari ShuggyCoUk di blog yang sama), menyoroti fragmentasi memori, dan gagal menyebutkan dampak ukuran file halaman (dan bagaimana hal itu dapat diatasi dengan penggunaan CreateFileMapping
fungsi ).
Batasan 2GB artinya randomNumbers
harus kurang dari 2GB. Karena array adalah kelas dan memiliki beberapa overhead sendiri, ini berarti array double
harus lebih kecil dari 2 ^ 31. Saya tidak yakin berapa jauh lebih kecil dari 2 ^ 31 Panjangnya harus, tetapi Overhead dari array NET.? menunjukkan 12 - 16 byte.
Fragmentasi memori sangat mirip dengan fragmentasi HDD. Anda mungkin memiliki ruang alamat 2GB, tetapi saat Anda membuat dan menghancurkan objek, akan ada celah di antara nilai-nilai tersebut. Jika celah ini terlalu kecil untuk objek besar Anda, dan ruang tambahan tidak dapat diminta, Anda akan mendapatkanSystem.OutOfMemoryException
. Misalnya, jika Anda membuat 2 juta, 1024 objek byte, maka Anda menggunakan 1.9GB. Jika Anda menghapus setiap objek yang alamatnya bukan kelipatan 3 maka Anda akan menggunakan memori .6GB, tetapi akan tersebar di seluruh ruang alamat dengan blok terbuka 2024 byte di antaranya. Jika Anda perlu membuat objek berukuran .2GB, Anda tidak akan dapat melakukannya karena tidak ada blok yang cukup besar untuk memuatnya dan ruang tambahan tidak dapat diperoleh (dengan asumsi lingkungan 32 bit). Solusi yang mungkin untuk masalah ini adalah hal-hal seperti menggunakan objek yang lebih kecil, mengurangi jumlah data yang Anda simpan di memori, atau menggunakan algoritma manajemen memori untuk membatasi / mencegah fragmentasi memori. Perlu dicatat bahwa kecuali Anda mengembangkan program besar yang menggunakan banyak memori, ini tidak akan menjadi masalah. Juga,
Karena sebagian besar program meminta memori kerja dari OS dan tidak meminta pemetaan file, program tersebut akan dibatasi oleh RAM sistem dan ukuran file halaman. Seperti dicatat dalam komentar oleh Néstor Sánchez (Néstor Sánchez) di blog, dengan kode terkelola seperti C # Anda terjebak pada batasan file RAM / halaman dan ruang alamat sistem operasi.
Itu jauh lebih lama dari yang diharapkan. Semoga membantu seseorang. Saya mempostingnya karena saya System.OutOfMemoryException
menjalankan program x64 pada sistem dengan RAM 24GB meskipun array saya hanya menyimpan barang 2GB.