2009-06-23 95 views
7

背景:我正在寫一個C++程序,處理大量的地理數據,並希望加載大塊進行一次處理。我受限於使用爲32位機器編譯的應用程序。我正在測試的機器運行的是64位操作系統(Windows 7),並具有6個RAM。使用MS VS 2008你應該能夠分配多少內存?

我有以下代碼:

byte* pTempBuffer2[3]; 
try 
{ 
    //size_t nBufSize = nBandBytes*m_nBandCount; 
    pTempBuffer2[0] = new byte[nBandBytes]; 
    pTempBuffer2[1] = new byte[nBandBytes]; 
    pTempBuffer2[2] = new byte[nBandBytes]; 
} 
catch (std::bad_alloc) 
{ 
    // If we didn't get the memory just don't buffer and we will get data one 
    // piece at a time. 
    return; 
} 

我希望我能夠分配內存,直到應用達到32位尋址的4 GB的限制。但是,當nBandBytes爲466,560,000時,新的第二次嘗試會拋出std :: bad_alloc。在這個階段,進程的工作集(內存)值是665,232 K因此,我似乎無法獲得分配的內存。

已經有一個2演出限制在32位Windows應用程序,其可以擴展到3演出和/ 3GB開關爲Win32一些提。這是在這種環境下的好建議,但與這種情況無關。

多少內存你應該能夠在64位操作系統下的分配與32位應用程序?

+0

我在網上發現了這個參考資料:「如果你在64位操作系統上作爲32位應用運行,那麼你可以獲得所有的4G地址空間,所有這些都可以由物理內存支持(如果你有RAM),即使沒有你自己使用64位指針。「從博客:http://blogs.msdn.com/ricom/archive/2009/06/10/visual-studio-why-is-there-no-64-bit-version。aspx – Bill 2009-06-23 18:10:11

+0

在我的32位機器上,我可以在簡單測試中分配466,560,000×3個字節。似乎是在你的情況下分配點處已經分散的進程內存。 – 2009-06-23 18:19:21

+1

我很難選擇一個答案來標記正確的這個問題。我相信答案很複雜,取決於很多因素。內存映射文件是一個很好的答案,但這個問題的根本原因似乎是內存碎片。 bke1指出了用於查看內存的好工具,許多人談論內存碎片,但我選擇了第一個明確指出問題並給出了嚴格限制的答案(64位下的4 GB和右側標記)。 – Bill 2009-06-23 19:16:50

回答

10

儘可能多的OS想給你。默認情況下,Windows允許32位進程擁有2GB的地址空間。這分成幾塊。爲堆棧預留一個區域,爲每個可執行文件和dll加載其他區域。剩下的東西可以動態分配,但不能保證它會成爲一個大的連續塊。它可能是幾個幾百MB的小塊。

如果與LARGEADDRESSAWARE標誌進行編譯,64位的Windows將讓您使用完整的4GB地址空間,這應該有點幫助,但總的來說,

  • 你不應該假設可用內存是連續的。您應該可以使用多個較小的分配而不是幾個較大的分配,並且
  • 如果需要大量內存,則應該將其編譯爲64位應用程序。
6

在Windows 32位,正常過程可能需要2 GB最大,但與/3GB開關它可達到3 GB(適用於Windows 2003)。

但在你的情況下,我認爲你是分配連續的內存,所以出現異常。

1

在nBandBytes爲466,560,000時,您試圖分配1.4 GB。 32位應用程序通常只能訪問2 GB內存(如果使用/ 3GB引導並且可執行文件標記爲可識別大地址空間,則應用程序更多)。你可能很難爲你的大塊內存找到許多連續地址空間塊。

如果你想在64位操作系統分配的內存千兆字節,使用一個64位的過程。

1

您應該能夠爲每個進程分配總共大約2GB的內存。 This article(PDF)解釋了詳細信息。但是,您可能無法獲得一個甚至接近這個大的連續塊。

1

即使你在較小的塊分配,你不能得到你所需要的內存,尤其是如果周圍的程序有不可預知的記憶行爲,或者如果您需要在不同的操作系統上運行。根據我的經驗,32位處理器上的堆空間大約爲1.2GB。

在這個內存量,我會建議手動寫入磁盤。將您的陣列封裝在管理內存的類中,並在必要時寫入臨時文件。希望您的程序的特點是,您可以有效地緩存部分數據,而不會過多地訪問磁盤。

4

您可以分配儘可能多的內存,因爲您的頁面文件可以讓您 - 即使沒有/ 3GB開關,您也可以毫不費力地分配4GB內存。

閱讀this article瞭解如何思考物理內存,虛擬內存和地址空間(這三者是不同的東西)。簡而言之,您擁有與RAM相同的物理內存,但您的應用程序實際上完全沒有與該物理內存的交互 - 它只是將數據存儲在虛擬內存中的便利之處。您的虛擬內存受到頁面文件大小的限制,您的應用程序可以使用的數量受到其他應用程序使用量的限制(儘管您可以分配更多,但實際上並未使用它)。你在32位世界中的地址空間是4GB。其中,2 GB分配給內核(如果使用/ 3BG開關,則爲1 GB)。在剩下的2GB中,有一些將被堆棧用完,一些則由您正在運行的程序(以及所有的dll等)耗盡。它會變得分散,而且你只能獲得如此多的連續空間 - 這是你的分配失敗的地方。但是由於該地址空間只是訪問爲您分配的虛擬內存的一種便捷方式,因此可以分配更多的內存,並且一次將幾塊內存分配到您的地址空間中。

Raymond Chen has an example如何分配4GB內存並將其部分映射到您的地址空間的一部分。

在32位Windows,最大可分配爲16TB和256TB在64位的Windows。

如果您真的瞭解內存管理在Windows中的工作原理,請參閱this article

2

在ElephantsDream項目Blender基金會與攪拌機3D過類似的問題(儘管在Mac)。不能包含鏈接,但谷歌:blender3d內存分配問題,它將成爲第一項。

該解決方案涉及文件映射。還沒有嘗試過,但你可以在這裏看到它:http://msdn.microsoft.com/en-us/library/aa366556(VS.85).aspx

1

Sysinternals VMMap非常適合研究虛擬地址空間碎片,這可能會限制你可以分配多少連續的內存。我建議將其設置爲顯示可用空間,然後按大小進行排序以查找最大空閒區域,然後按地址進行排序以查看將最大空閒區域(可能是已重新綁定的DLL,共享內存區域或其他堆)分開的內容。

避免非常大的連續分配是可能是最好的,正如其他人建議。

設置LARGE_ADDRESS_AWARE=YES(如jalf建議)是很好的,只要你的應用程序依賴的庫與它兼容即可。如果這樣做,則應該使用AllocationPreference註冊表項集測試代碼,以啓用自頂向下虛擬地址分配。