2010-11-03 41 views
4

我需要分配非常大的簡單結構數組(1 GB RAM)。經過一些分配/釋放後,內存變爲碎片並引發OutOfMemory異常。C#分塊數組

這是32位以下。由於我獲得的性能損失,我寧願不使用64位 - 相同的應用程序在64位模式下運行速度降低30%。

您是否知道IList兼容陣列的一些實現,它們以塊的形式分配內存,而不是一次全部分配內存?這將避免我的記憶碎片問題。

+0

奇怪的是,這是真的*錯誤的問題。它應該問「爲什麼64位程序慢30%?」分塊數組後,你的32位進程也會變得很慢。 – 2010-11-03 16:31:53

+0

最初的應用程序是64位,但在閱讀了一些文章後發現,64位JIT並不擅長優化32位代碼(http:// stackoverflow。com/questions/14432/64bit-net-performance-tuning),我將它轉換爲32位,並發現這是真實的。即使我在這裏速度有所下降,它的啓動速度仍將高於64位版本 - 我使用的是IronPython + C#+ C++/CLI,64位版本的啓動時間延長了10秒(由於IronPython) – Meh 2010-11-03 16:59:35

回答

3

喬希·威廉姆斯採用分塊陣列呈現在他的博客BigArray<T>類:

BigArray<T>, getting around the 2GB array size limit

你會發現此相關的問題更多有用信息:

C# huge size 2-dim arrays

一個簡單的臨時修復可能是爲您的應用程序啓用3GB開關。這樣做可以讓您的應用程序使用超過32位Windows的每進程2GB限制。但是請注意,CLR允許的最大對象大小仍然是2GB。交換機可以用後置內置動作爲您的主執行程序被啓動:

call "$(DevEnvDir)..\tools\vsvars32.bat" 
editbin.exe /LARGEADDRESSAWARE "$(TargetPath)" 
+0

我已經完成了/ LARGEADDRESSAWARE技巧,它爲#2,simple和parsimonius提供了很多 – Meh 2010-11-03 15:17:43

1

當實例化一個數組,淨試圖找到的存儲器來儲存陣列連續一部分。由於32位應用程序的總內存限制爲2Gb,因此您可以看到在多次分配之後找到這樣的塊將非常困難。

  1. 您可以嘗試使用一些像LinkedList<T>,以避免連續分配的需要,或者調整你的代碼,使這些塊更小的(雖然你不會是完全安全的,這將不是一個500MB陣列發生也)。

  2. 另一方面,一種解決方案是在您的應用程序啓動時只實例化一次這個大緩衝區,然後實現一個算法,在應用程序的整個生命週期中重用這個相同的空間。

  3. 如果您可以使用IEnumerable而不是IList將數據傳遞給程序的其餘部分,那麼您可以使用SelectMany LINQ方法摺疊該列表。

  4. 最後,您可以簡單地在自定義類中實現IList接口,並在引擎蓋下使用幾個較小的數組。

+0

+1 – smirkingman 2010-11-03 16:10:39