3 回答

TA貢獻1824條經驗 獲得超8個贊
您可能需要閱讀以下內容:Eric Lippert的“ “內存不足”不涉及物理內存 ”。
簡而言之,并且非常簡化,“內存不足”并不真正意味著可用內存量太小。最常見的原因是,在當前地址空間內,沒有連續的內存部分足夠大以服務于所需的分配。如果您有100個塊,每個塊4 MB,那么當您需要一個5 MB塊時,這將無濟于事。
關鍵點:
在我看來,我們稱之為“進程存儲器”的數據存儲最好可視化為磁盤上的海量文件。
RAM可以看作僅僅是性能優化
程序消耗的虛擬內存總量實際上與它的性能沒有太大關系
很少“用完RAM”會導致“內存不足”錯誤。它導致錯誤的性能,而不是錯誤,因為存儲實際上在磁盤上這一事實的全部成本突然變得很重要。

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的東西。
- 3 回答
- 0 關注
- 743 瀏覽
添加回答
舉報