[英]When writing a large array directly to disk in MATLAB, is there any need to preallocate?
問:增長陣列會產生相同的性能影響,如果是這樣,那么與寫入磁盤所需的時間相比,它會顯着嗎?
答:是的,如果您在沒有預先分配的情況下顯着增加磁盤上的文件,性能將受到影響。 性能受到影響將是碎片化的結果。 正如您所提到的,如果文件是在一個會話中編寫的,則碎片風險較小,但如果文件顯着增長則會導致問題。
MathWorks網站上提出了一個相關問題 ,接受的答案是盡可能預先分配。
如果您沒有預先分配,那么您的性能問題的程度將取決於:
讓我們假裝您正在運行最近的Windows操作系統,因此使用NTFS文件系統 。 讓我們進一步假設它已經設置為默認的4 kB簇大小。 因此,磁盤空間以4 kB塊的形式分配,並將這些位置索引到主文件表。 如果文件增長且連續空間不可用,則只有兩種選擇:
文件系統選擇執行最不好的選項#2,並更新MFT記錄以指示新群集在磁盤上的位置。
現在,硬盤需要物理地移動讀頭以便讀取或寫入新簇,這是一個(相對)慢的過程。 在移動磁頭方面,等待磁盤的正確區域在其下面旋轉......你可能正在尋找大約10ms的尋道時間。 因此,每次敲擊碎片時,HDD都會有額外的10ms延遲,以便訪問新數據。 SSD具有更短的尋道時間(沒有移動部件)。 為簡單起見,我們忽略了多盤系統和RAID陣列!
如果你在不同的時間繼續增長文件,那么你可能會遇到很多碎片。 這實際上取決於文件的增長時間/數量,以及您使用硬盤的方式。 您遇到的性能影響還取決於您閱讀文件的頻率以及您遇到片段的頻率。
MATLAB以列主要順序存儲數據,並且從注釋中看起來您有興趣對數據集執行逐列操作(總和,平均值)。 如果列在磁盤上變得不連續,那么你將在每次操作時擊中大量碎片!
如評論中所述,讀取和寫入操作都將通過緩沖區執行。 正如@ user3666197指出的那樣,操作系統可以推測性地預讀磁盤上的當前數據,因為您可能希望接下來的數據。 如果硬盤有時處於空閑狀態 - 保持其以最大容量運行並且在緩沖存儲器中處理小部分數據可以極大地提高讀寫性能,則此行為尤其有用。 但是,從你的問題來看,聽起來好像你想對一個巨大的(太大的內存).mat文件執行大型操作。 鑒於您的用例,硬盤無論如何都將以容量工作,而且數據文件太大而無法容納緩沖區 - 因此這些特殊技巧無法解決您的問題。
所以......是的,你應該預先分配。 是的,在磁盤上增加陣列的性能會受到影響。 是的,它可能會很重要(這取決於具體的增長量,碎片等)。 如果你真的要深入了解HPC的精神,那么就停止你正在做的事情,拋棄MATLAB,破壞你的數據並嘗試類似Apache Spark的東西! 但這是另一個故事。
這是否回答你的問題?
PS更正/修正歡迎! 我是在POSIX inode上長大的,如果這里有任何不准確之處,我真誠地道歉......
在RAM中預先分配變量並在磁盤上預分配不能解決同樣的問題。
為了在RAM中擴展矩陣,MATLAB創建一個具有新大小的新矩陣,並將舊矩陣的值復制到新矩陣中並刪除舊矩陣。 這會花費很多性能。
如果預先分配了矩陣,則其大小不會改變。 所以沒有理由讓MATLAB再次進行矩陣復制。
GnomeDePlume說,硬盤上的問題是碎片化 。 即使文件是在一個會話中編寫的,碎片仍然是一個問題。
原因如下:硬盤通常會有點碎片化。 想像
#
是硬盤上已滿的內存塊 M
是硬盤上用於保存矩陣數據的內存塊 -
成為硬盤上的空閑內存塊 現在,在將矩陣寫入其中之前,硬盤可能看起來像這樣:
###--##----#--#---#--------------------##-#---------#---#----#------
當您編寫矩陣的某些部分(例如MMM
塊)時,您可以想象這個過程看起來像這樣>!(我舉一個例子,文件系統將從左到右依次使用第一個足夠大的空閑空間 -真實的文件系統是不同的):
###--##MMM-#--#---#--------------------##-#---------#---#----#------
###--##MMM-#--#MMM#--------------------##-#---------#---#----#------
###--##MMM-#--#MMM#MMM-----------------##-#---------#---#----#------
顯然,雖然我們在沒有做任何其他事情的情況下編寫它,但硬盤上的矩陣文件仍然是碎片化的。
如果矩陣文件已預先分配,這可能會更好。 換句話說,我們告訴文件系統我們的文件有多大,或者在這個例子中,我們要為它保留多少內存塊。
想象一下矩陣需要12個塊: MMMMMMMMMMMM
。 我們通過預先分配告訴文件系統我們需要這么多,它將盡可能地滿足我們的需求。 在這個例子中,我們很幸運:有大於= 12個內存塊的可用空間。
###--##----#--#---# (------------) --------##-#---------#---#----#------
###--##----#--#---# (MMM---------) --------##-#---------#---#----#------
###--##----#--#---# (MMMMMM------) --------##-#---------#---#----#------
###--##----#--#---# (MMMMMMMMM---) --------##-#---------#---#----#------
###--##----#--#---# (MMMMMMMMMMMM) --------##-#---------#---#----#------
Voilá,沒有碎片!
一般來說,您可以將此過程想象為購買大型團體的電影票。 你想團結在一起,但是劇院里已經有一些座位由其他人保留。 為了使收銀員能夠滿足您的要求(大型團隊想要團結在一起),他/她需要了解您的團隊有多大(預分配)。
快速回答整個討論(如果您沒有時間關注或技術理解):
因此,如果您不能一次寫入, 請將寫入分成大塊 。
這個答案基於作者在最近一周提供的原始帖子和澄清 (兩者)。
由文件系統和文件訪問層引入的低級,物理媒體相關的“碎片”引入的不良性能影響問題在TimeDOMAIN幅度和ComputingDOMAIN重復性中進一步面臨其中有這種方法的實際問題 。
最后 , 提出了針對給定任務的最先進的, 主要是最快的可能解決方案 ,以便最大限度地減少浪費的努力和錯誤解釋錯誤對理想化或其他無效假設造成的損害,類似於“嚴重文件碎片化”的風險由於一個假設,整個文件將在一個會話中寫入(這在當代O / S的許多多核/多進程操作中實際上在一段時間內實際上是不可能的) -creation和一系列廣泛的修改(參考MATLAB大小限制)在當代COTS文件系統內的TB大小的BLOB文件對象。
人們可能會討厭事實,但事實仍然存在,直到更快更好的方法進入
真正的性能不利影響不是由HDD-IO 引起的 , 也不是與文件碎片有關
RAM 不是 .mat
文件的半永久存儲的替代方案
鑒於:
整個處理只運行一次 ,沒有優化/迭代,沒有連續處理
數據有1E6
double
浮點值x 1E5
列=約0.8 TB
(+ HDF5
開銷)
盡管有原始帖子,但沒有與處理相關的隨機IO
數據采集階段與.NET通信,以將DataELEMENT
接收到MATLAB中
這意味着,從v7.4開始,
基於32位Win的MATLAB WorkSpace的1.6 GB limit
(帶3GB交換機的2.7 GB)
對於wXP / 1.4 GB wV / 1.5 GB中MATLAB最大矩陣的1.1 GB limit
對於32位Linux操作系統中最大的Matrix,MATLAB WorkSpace + 2.3 GB限制有點“釋放” 2.6 GB limit
。
具有64位O / S將無法幫助任何類型的32位MATLAB 7.4實現,並且由於另一個限制 (陣列中的最大單元數量) 將無法工作 ,這將不包括此處請求的1E12。
唯一的機會是兩者都有
和 64位MATLAB 7.5+
數據存儲階段假定行排序數據塊(行排序數據塊的集合)的塊寫入到HDD設備上的MAT-file
數據處理階段假定在獲取所有輸入並將所有輸入編組到基於文件的脫RAM存儲之后,在HDD設備上的MAT-file
重新處理數據,但是以列順序的方式
只需按列計算mean()
s / max()
es需要計算( 不再復雜 )
事實:
HDF5
文件結構的“受限制”實現。 檢查實際數據和真實硬件(HDD + SSD)的性能測量,以獲得其不可避免的弱點的尺度感
分層數據格式( HDF
)誕生於1987年的國家超級計算應用中心( NCSA ),大約20年前。 是的,那個老了。 目標是開發一種文件格式,結合靈活性和效率來處理極大的數據集。 不知何故HDF文件沒有在主流中使用,因為只有少數幾個行業確實能夠真正利用它的可怕能力或根本不需要它們。
靈活性意味着文件結構帶來一些開銷,如果數組內容沒有變化就不需要使用(你付出成本而不消耗使用它的任何好處),並假設HDF5
限制了數據的整體大小它可以包含一些幫助並保存MATLAB方面的問題是不正確的。
MAT-files
原則上是好的,因為它們避免了需要將整個文件加載到RAM中以便能夠使用它。
然而, MAT-files
不能很好地完成這里定義和澄清的簡單任務。 試圖這樣做只會導致性能不佳和HDD-IO文件碎片(在write-through
期間增加幾十毫秒,而在計算期間少於read-ahead
)將無濟於事根本就是判斷整體表現不佳的核心原因。
而不是將整個龐大的1E12
DataELEMENT
集合移動到MATLAB內存代理數據陣列中,而不是僅為下一個即將到來的HDF5
/ MAT-file
HDD設備IO-s( write-through
s和O)序列流安排/ S與硬件 - 設備鏈沖突/次優化預read-ahead
s)以便讓所有的巨大工作“只是[已婚]已准備好”進行一些簡單的調用mean()
/ max()
MATLAB功能(將盡力以另一種順序改進每個1E12
DataELEMENT
( 甚至是TWICE - 是的 -在第一個作業處理夢魘完全停止后, 通過所有HDD-IO的另一個馬戲團) 瓶頸 )回到MATLAB in-RAM-objects中, 從一開始就將這一步重新設計 為管道BigDATA處理。
while true % ref. comment Simon W Oct 1 at 11:29
[ isStillProcessingDotNET, ... % a FLAG from .NET reader function
aDotNET_RowOfVALUEs ... % a ROW from .NET reader function
] = GetDataFromDotNET( aDtPT ) % .NET reader
if ( isStillProcessingDotNET ) % Yes, more rows are still to come ...
aRowCOUNT = aRowCOUNT + 1; % keep .INC for aRowCOUNT ( mean() )
for i = 1:size( aDotNET_RowOfVALUEs )(2) % stepping across each column
aValue = aDotNET_RowOfVALUEs(i); %
anIncrementalSumInCOLUMN(i) = ...
anIncrementalSumInCOLUMN(i) + aValue; % keep .SUM for each column ( mean() )
if ( aMaxInCOLUMN(i) < aValue ) % retest for a "max.update()"
aMaxInCOLUMN(i) = aValue; % .STO a just found "new" max
end
endfor
continue % force re-loop
else
break
endif
end
%-------------------------------------------------------------------------------------------
% FINALLY:
% all results are pre-calculated right at the end of .NET reading phase:
%
% -------------------------------
% BILL OF ALL COMPUTATIONAL COSTS ( for given scales of 1E5 columns x 1E6 rows ):
% -------------------------------
% HDD.IO: **ZERO**
% IN-RAM STORAGE:
% Attr Name Size Bytes Class
% ==== ==== ==== ===== =====
% aMaxInCOLUMNs 1x100000 800000 double
% anIncrementalSumInCOLUMNs 1x100000 800000 double
% aRowCOUNT 1x1 8 double
%
% DATA PROCESSING:
%
% 1.000.000x .NET row-oriented reads ( same for both the OP and this, smarter BigDATA approach )
% 1x INT in aRowCOUNT, %% 1E6 .INC-s
% 100.000x FLOATs in aMaxInCOLUMN[] %% 1E5 * 1E6 .CMP-s
% 100.000x FLOATs in anIncrementalSumInCOLUMN[] %% 1E5 * 1E6 .ADD-s
% -----------------
% about 15 sec per COLUMN of 1E6 rows
% -----------------
% --> mean()s are anIncrementalSumInCOLUMN./aRowCOUNT
%-------------------------------------------------------------------------------------------
% PIPE-LINE-d processing takes in TimeDOMAIN "nothing" more than the .NET-reader process
%-------------------------------------------------------------------------------------------
您的管道 d BigDATA計算策略將以智能方式主要避免 MATLAB中的臨時存儲緩沖,因為它將逐步計算不超過約3 x 1E6
ADD / CMP寄存器的結果,所有這些都具有靜態布局, 避免代理 -存儲到HDF5
/ MAT-file
, 絕對避免所有與HDD-IO相關的瓶頸和低BigDATA持續讀取的速度(完全沒有談到臨時/ BigDATA持續寫入...)並且還可以避免不良內存-mapped僅用於計算mean-s和max-es。
太陽下的管道處理並不是什么新鮮事。
它重復使用速度導向的HPC解決方案已經使用了幾十年
[BigDATA標簽之前的幾代人已經在營銷部門“發明”了。 ]
忘掉數以萬計的HDD-IO阻塞操作,並進入流水線分布式流程到流程解決方案。
如果是的話 ,所有外匯業務和HFT對沖基金怪獸都已經存在......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.