MATLAB的記憶體管理是自動完成的,但記憶體使用不當會造成程式執行效率低下。許多初學者抱怨MATLAB程式慢(效率低),主要原因可能是不瞭解MATLAB的記憶體自動管理機制造成的。
MATLAB是以陣列(Array)為基本資料單元的一門語言,程式中的一切資料都是陣列。MATLAB用連續的記憶體來儲存數值型陣列,當陣列大小發生變化時會重新分配一塊合適的記憶體,把資料複製過去並回收原來的記憶體。如果陣列是在程式執行過程中逐漸“長大”的,MATLAB會反覆分配和回收記憶體,嚴重影響程式的執行效率。為了避免這種情況,可以用zeros函式預先為陣列分配合適的記憶體,然後再對其進行賦值。
另外,MATLAB陣列在記憶體中是按“列優先”的順序存放陣列中的元素的。對於多維陣列,是按從低到高的維度順序依次儲存陣列中的元素的,如下圖所示
圖中紅色的序號即為陣列在記憶體中的儲存順序。在程式中對陣列進行索引或賦值時,如果能夠按照這種順序來儲存,一方面可以利用計算機的快取機制,另一方面可以避免程式在記憶體中的不斷跳轉,從而可以顯著地提高程式的執行效率。如果透過多重迴圈來存取資料,遵照此原則,最內層迴圈應該遍歷最低維(列),從內向外,依次向高維過渡。
下面的程式可以比較預分配記憶體和索引順序對程式執行時間的影響:
% 陣列索引效率比較clearpreAllocate = 'on'; %設為off關閉預分配記憶體r = 10000;c = 10000;ticif isequal(preAllocate,'on') A = zeros(r,c); %預分配記憶體else preAllocate = 'off';endfor m=1:r %行優先 for n=1:c A(m,n) = m+n; endendfprintf('行優先,預分配記憶體 %s, 耗時 \t%f\n',upper(preAllocate),toc)ticif isequal(preAllocate,'on') B = zeros(r,c); %預分配記憶體endfor n=1:c %列優先 for m=1:r B(m,n) = m+n; endendfprintf('列優先,預分配記憶體 %s, 耗時 \t%f\n',upper(preAllocate),toc)
看一下不同情況下的耗時對比
行優先,預分配記憶體 OFF, 耗時 407.735436列優先,預分配記憶體 OFF, 耗時 1.346732行優先,預分配記憶體 ON, 耗時 1.149516列優先,預分配記憶體 ON, 耗時 0.412534
可以看出,記憶體使用不當可以造成近千倍的效率差別。是因為MATLAB慢嗎?
一言以蔽之,為陣列預分配記憶體並遵循“列優先”的原則使用陣列中的資料,是提高MATLAB效率的有效途徑。
幾點說明:
不同型別的陣列在記憶體中的儲存方式也不盡相同,單一資料型別的陣列,如數值型陣列和字元型陣列,在記憶體中是連續儲存的。而容器型資料的底層單元則可以分開儲存,例如,結構陣列一般每個域用連續的記憶體儲存,不同的域則可以存在不同的位置。這是容器型資料的優勢,區域性改動不會影響其他部分。稀疏矩陣僅儲存非零元素及其下標。不同型別的陣列預分配記憶體的方式也不一樣。例如數值型陣列一般用zeros函式;字串型陣列用strings函式;元胞陣列用cell函式;表則用table函式。詳情可在命令列doc preallocation。
最新評論