Muhtemelen anladığınız gibi, sorun, bellek parçalanması nedeniyle çalışmayan büyük bir bitişik bellek bloğu ayırmaya çalışmanızdır. Yaptığınız şeyi yapmam gerekirse, şunları yapardım:
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];
}
Ardından, kullanacağınız belirli bir dizini almak için randomNumbers[i / sizeB][i % sizeB]
.
Değerlere her zaman sırayla erişirseniz başka bir seçenek , tohumu belirtmek için aşırı yüklenmiş yapıcıyı kullanmak olabilir . Bu şekilde yarı rasgele bir sayı elde edersiniz (gibi DateTime.Now.Ticks
) onu bir değişken içinde depolar, sonra listeye her başladığınızda orijinal tohumu kullanarak yeni bir Random örneği oluşturursunuz:
private static int randSeed = (int)DateTime.Now.Ticks;
private static Random GetNewRandomIterator()
{
return new Random(randSeed);
}
Fredrik Mörk'ün cevabında bağlantısı verilen blog, sorunun genellikle adres alanı eksikliğinden kaynaklandığını belirtmesine rağmen, 2GB CLR nesne boyutu sınırlaması gibi bir dizi başka sorunu listelemediğini belirtmek önemlidir ( ShuggyCoUk aynı blogda), bellek parçalanmasına değiniyor ve sayfa dosya boyutunun etkisinden (ve CreateFileMapping
işlevin kullanılmasıyla nasıl ele alınabileceğinden) bahsetmiyor .
2GB sınırlaması, randomNumbers
2GB'den az olması gerektiği anlamına gelir . Diziler sınıflar olduklarından ve kendilerinin bir miktar ek yüküne sahip olduklarından, bu, dizinin double
2 ^ 31'den küçük olması gerektiği anlamına gelir . Uzunluğun 2 ^ 31'den ne kadar küçük olması gerektiğinden emin değilim, ancak bir .NET dizisinin Ek yükü? 12 - 16 baytı gösterir.
Bellek parçalanması, HDD parçalanmasına çok benzer. 2GB adres alanınız olabilir, ancak nesneleri oluşturup yok ederken değerler arasında boşluklar olacaktır. Bu boşluklar büyük nesneniz için çok küçükse ve ek alan talep edilemiyorsa, o zaman alacaksınızSystem.OutOfMemoryException
. Örneğin, 2 milyon 1024 baytlık nesne oluşturursanız, 1,9 GB kullanırsınız. Adresin 3'ün katı olmadığı her nesneyi silerseniz, .6GB bellek kullanırsınız, ancak adres alanı boyunca 2024 bayt açık bloklar arasında yayılır. Eğer .2GB büyüklüğünde bir nesne oluşturmanız gerekiyorsa, bunu yapamazsınız, çünkü onu sığdırmak için yeterince büyük bir blok yoktur ve ek alan elde edilemez (32 bitlik bir ortam varsayılarak). Bu sorunun olası çözümleri, daha küçük nesneler kullanmak, bellekte depoladığınız veri miktarını azaltmak veya bellek parçalanmasını sınırlamak / önlemek için bir bellek yönetimi algoritması kullanmak gibi şeylerdir. Büyük miktarda bellek kullanan büyük bir program geliştirmediğiniz sürece bunun bir sorun olmayacağına dikkat edilmelidir. Ayrıca,
Çoğu program işletim sisteminden çalışma belleği talep ettiğinden ve bir dosya eşleme istemediğinden, bunlar sistemin RAM'i ve sayfa dosya boyutu ile sınırlandırılacaktır. Blogda Néstor Sánchez'in (Néstor Sánchez) yaptığı yorumda belirtildiği gibi, C # gibi yönetilen bir kodla RAM / sayfa dosyası sınırlamasına ve işletim sisteminin adres alanına bağlı kalıyorsunuz.
Bu beklenenden çok daha uzundu. Umarım birine yardımcı olur. Bunu gönderdim çünkü System.OutOfMemoryException
dizimde sadece 2GB'lık şeyler olmasına rağmen 24GB RAM'li bir sistemde bir x64 programı çalıştırmaya başladım.