2014-07-03 27 views
2

我目前正在構建一個代碼,它動態地處理使用向量類的大量內存。只有存在足夠的內存時,才能使用向量push_back

該代碼正在構建與push_back的矢量,其中重要的是要注意向量是2維的,表示數據矩陣。根據情況,這個矩陣可能很小,或者變得特別大。

例如,數據矩陣可以有幾行,每行有1000列,或者它可以獲得1000行,列數相同,充滿雙數據類型。很明顯,這很容易成爲問題,因爲1000x1000x8 = 8 000 000字節,因此表示8 MB內存。但是,如何增加10倍的行數和10倍的行數呢? (這很容易發生在我的代碼中)。

我正在通過將數據矩陣寫入硬盤驅動器來解決這個問題,但是這種方法相當慢,因爲我沒有充分使用內存。

我的問題: 如何建立使用push_backvector< vector<double> >代表這個矩陣,但只有在有可分配足夠的內存。

如果內存數量不足,我會繼續將數據導出到一個文件中,釋放分配的內存並啓動循環。我不知道的是如何檢查每個執行的push_back內存是否可用。

編輯: 我應該注意到,我使用的是運行Ubuntu的64位機器。我不太確定如何以及OS分頁是否正在運行,但是我實際上正在做的是在存在電場和磁場的情況下對粒子進行數值計算。可以有超過1000個時間步進的1億個粒子,這是大量的GB數據。但是,有時候我只運行幾十萬個粒子來進行適合RAM的測試,而不會出現問題,從而加速了計算過程。我正在嘗試創建一些通用的解決方案來檢查是否有足夠的內存用於其他計算,如果沒有,則將它們移動到文件中。這些粒子可以添加到系統中或從中流出,所以基本上我不知道矩陣在任何給定時間有多大。這就是爲什麼我需要「好的就夠了,將這些數據移出這裏,以便我們可以重新開始」方法。

+1

使用自定義分配器,當您達到內存閾值時會失敗? –

+3

try {v.push_back()} catch(std :: bad_alloc&e){free_stuff()} http://stackoverflow.com/questions/7749066/how-to-catch-out-of-memory-exception-in- c –

+1

可能值得注意的是,底層操作系統會根據需要(頁面)將頁面刷新到磁盤,所以值得信任操作系統提供所需的虛擬化,而不是自己處理它。這意味着您的進程可以使用比機器上存在的物理內存更多的內存。 – millinon

回答

3

幾乎所有的替代品「我將數據推送到磁盤在我的代碼」比這更好。這是因爲操作系統本身(如果我們談論的是合理的現代操作系統,比如Windows NT家族和Unix的大部分變種,包括Linux和MacOS X)都有能力處理虛擬內存和交換到磁盤,並且它將以比您可能想出的更聰明的方式來實現。

此外(根據託尼D的評論),使用「內存映射文件」是一種比手動讀取/寫入文件更好的方法 - 這不會立即與std::vector或其他標準集合,但可能是一個比手動處理應用程序中的讀/寫文件更好的選擇 - 您只需說出「這是一個文件,請給我一個指向代表該文件的內存的指針」,然後使用該指針就好像該文件已加載到記憶。操作系統將負責管理文件的哪些部分實際上在任何給定時間物理地存在於內存中,類似於如果分配的內存多於系統中存在的內存,則交換進入和退出。如果您使用的是32位計算機(或32位計算機),則可以使用32位計算機(或32位計算機) bit操作系統或32位應用程序),可用於您的進程的最大內存量將介於2GB和4GB之間 - 完全取決於操作系統的限制(帶有32位應用程序的64位操作系統可能會爲您提供將近4GB ,32位Windows的常規設置總共約2GB),所以如果你的數組足夠大,那麼地址中就不會有足夠的位來跟蹤它,在這一點上你需要分割工作或者去64位操作系統和應用程序(當然這裏需要一個64位處理器),在這種情況下,內存大小的限制可以達到128或256TB(如果我的心理算法工作 - 65536 * 4GB)總共 - 這可能超過近e非常有磁盤空間,不用介意RAM。

編輯:

否則根據你給數據一些數學:與具有X每個粒子,Y,Z位置,速度,和「其他性能」將佔用6 * 8 = 48字節double,以及6 * 4 = 24字節作爲float

乘以100M,我們得到4.8GB的一組數據。次數1000次,使得4.8TB的數據。即使你擁有非常大的內存,這也是一個巨大的數字。使用mememory映射文件並不是真的可以一次將所有這些數據保存在內存中。如果你的計算機具有相當數量的內存(16GB左右),那麼每次在內存中保存兩組內存很可能會起作用。但是,您仍然在製作大量需要在某個時間點存儲的數據,而這些數據很可能會佔用大部分時間。對於一個相當現代化的(單個)硬盤,大約50-100MB/s是合理的預期。它可以通過某些RAID配置得到改進,但即使是這樣,它也是每秒數百兆字節,而不是每秒千兆字節。因此,以100MB /秒的速度存儲1TB(1000GB)將需要10000s或大約3個小時。 15個小時4.8TB。這只是存儲的數據,沒有計算[雖然這可能是一個最小的部分]。即使我們將數據集除以10,我們也有一個多小時,除以50,我們在分鐘範圍內下降。

無論您使用什麼方法,存儲和檢索這樣的大型數據集都是非常耗時的。內存映射文件在很多方面都是「最不好的」,因爲它在這個過程中稍微複製了一些數據。但它仍然是「磁盤速度」,它將成爲計算速度的主要因素。

+0

通常是很好的見解(因此早期的+1),但是應用程序可能需要在程序員不能自由指定交換空間量的機器上工作,因此偶爾會顯式創建內存映射文件或其他形式的I/O到非「交換」的磁盤可能是必要的... –

+0

@TonyD:謝謝。添加了內存映射文件的一部分,這是一個很好的建議,應該在那裏。 –

+0

謝謝,我會查找它,這似乎是一種方式。 – bluecore

相關問題