亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當仍有大量可用內存時,拋出“ System.OutOfMemoryException”

當仍有大量可用內存時,拋出“ System.OutOfMemoryException”

C#
喵喵時光機 2019-11-12 10:59:55
這是我的代碼:int size = 100000000;double sizeInMegabytes = (size * 8.0) / 1024.0 / 1024.0; //762 mbdouble[] randomNumbers = new double[size];異常:引發了類型為'System.OutOfMemoryException'的異常。我在這臺機器上有4GB內存,當我開始運行時有2.5GB可用空間,顯然PC上有足夠的空間來處理762mb的100000000隨機數。給定可用內存,我需要存儲盡可能多的隨機數。當我投入生產時,包裝盒上將有12GB,我想利用它。CLR是否將我限制為默認的最大內存開始?以及我如何要求更多?更新資料我認為如果問題是由于內存碎片造成的話,將它分成較小的塊并逐步增加我的內存需求會有所幫助,但是不管我做什么調整blockSize,我都無法超過256mb的ArrayList大小。private static IRandomGenerator rnd = new MersenneTwister();private static IDistribution dist = new DiscreteNormalDistribution(1048576);private static List<double> ndRandomNumbers = new List<double>();private static void AddNDRandomNumbers(int numberOfRandomNumbers) {    for (int i = 0; i < numberOfRandomNumbers; i++) {      ndRandomNumbers.Add(dist.ICDF(rnd.nextUniform()));                  }}從我的主要方法:int blockSize = 1000000;while (true) {  try  {    AddNDRandomNumbers(blockSize);                      }  catch (System.OutOfMemoryException ex)  {    break;  }}            double arrayTotalSizeInMegabytes = (ndRandomNumbers.Count * 8.0) / 1024.0 / 1024.0;
查看完整描述

3 回答

?
有只小跳蛙

TA貢獻1824條經驗 獲得超8個贊

您可能需要閱讀以下內容:Eric Lippert的“ “內存不足”不涉及物理內存 ”。

簡而言之,并且非常簡化,“內存不足”并不真正意味著可用內存量太小。最常見的原因是,在當前地址空間內,沒有連續的內存部分足夠大以服務于所需的分配。如果您有100個塊,每個塊4 MB,那么當您需要一個5 MB塊時,這將無濟于事。

關鍵點:

  • 在我看來,我們稱之為“進程存儲器”的數據存儲最好可視化為磁盤上海量文件。

  • RAM可以看作僅僅是性能優化

  • 程序消耗的虛擬內存總量實際上與它的性能沒有太大關系

  • 很少“用完RAM”會導致“內存不足”錯誤。它導致錯誤的性能,而不是錯誤,因為存儲實際上在磁盤上這一事實的全部成本突然變得很重要。


查看完整回答
反對 回復 2019-11-12
?
慕少森

TA貢獻2019條經驗 獲得超9個贊

您可能已經發現,問題在于您正在嘗試分配一個大的連續內存塊,由于內存碎片,該內存塊不起作用。如果我需要做您正在做的事情,請執行以下操作:


int sizeA = 10000,

? ? sizeB = 10000;

double sizeInMegabytes = (sizeA * sizeB * 8.0) / 1024.0 / 1024.0; //762 mb

double[][] randomNumbers = new double[sizeA][];

for (int i = 0; i < randomNumbers.Length; i++)

{

? ? randomNumbers[i] = new double[sizeB];

}

然后,要獲取特定索引,請使用randomNumbers[i / sizeB][i % sizeB]。


如果您始終按順序訪問這些值,則另一個選擇可能是使用重載的構造函數來指定種子。這樣,您將獲得一個半隨機數(如DateTime.Now.Ticks),將其存儲在變量中,然后無論何時開始瀏覽列表,都將使用原始種子創建一個新的Random實例:


private static int randSeed = (int)DateTime.Now.Ticks;? //Must stay the same unless you want to get different random numbers.

private static Random GetNewRandomIterator()

{

? ? return new Random(randSeed);

}

重要的是要注意,盡管該問題通常是由于地址空間不足所致,但并未列出其他許多問題,例如2GB CLR對象大小限制(在ShuggyCoUk在同一博客上)掩蓋了內存碎片,并且沒有提及頁面文件大小的影響(以及如何使用CreateFileMapping函數解決)。


2GB的限制意味著randomNumbers 必須小于2GB。由于數組是類,并且它們自身具有一些開銷,因此這意味著數組double必須小于2 ^ 31。我不確定長度必須比2 ^ 31小多少,但是.NET數組的開銷?表示12-16個字節。


內存碎片與HDD碎片非常相似。您可能有2GB的地址空間,但是在創建和銷毀對象時,這些值之間會有間隙。如果這些間隙對于您的大物件而言太小,并且無法請求額外的空間,那么您將獲得System.OutOfMemoryException。例如,如果您創建200萬個1024字節的對象,則您使用的是1.9GB。如果刪除地址不是3的倍數的每個對象,則將使用.6GB的內存,但是它將在整個地址空間中分布,中間有2024字節的開放塊。如果您需要創建一個大小為.2GB的對象,則將無法執行該操作,因為沒有足夠大的塊可容納該塊,并且無法獲得額外的空間(假定為32位環境)。解決此問題的方法可能是使用較小的對象,減少存儲在內存中的數據量或使用內存管理算法限制/防止內存碎片。應該注意的是,除非您正在開發使用大量內存的大型程序,否則這將不是問題。也,


由于大多數程序從操作系統請求工作內存,并且不請求文件映射,因此它們將受到系統RAM和頁面文件大小的限制。


那比預期更長。希望它可以幫助某人。我發布它是因為我遇到了在System.OutOfMemoryException具有24GB RAM的系統上運行x64程序的問題,即使我的陣列僅容納2GB的東西。


查看完整回答
反對 回復 2019-11-12
  • 3 回答
  • 0 關注
  • 743 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號