Matlab內存管理/調優/優化問題(轉載)

感謝原文博主,因無法轉載,所以直接copy過來了:

原文鏈接:https://blog.csdn.net/liuyue2046/article/details/8224198

以下爲正文:

用 Matlab 進行大規模科學計算或仿真時,內存是一個需要時常注意的問題。在matlab裏運行

>>system_dependent memstats

就可以看到內存的使用狀況。當你寫的 Matlab 程序跳出“Out of Memory” 時,以下幾點措施是需要優先考慮的解決方法:

1. 升級內存

2. 升級64位系統

3. 增加虛擬內存

4. 採用3GB開關啓動系統

由於32位 Windows 操作系統的限制,每個進程只能使用最多 2GB 的虛擬內存地址空間,因此 Matlab 的可分配內存也受到相應的限制。Matlab 7.0.1 引進了新的內存管理機制,可以利用 Windows 的 3GB 開關,使用 3GB 開關啓動的 Windows 每個進程可以在多分配 1 GB 的虛擬地址空間。具體做法是:修改C盤根目錄 boot.ini 啓動選項加上 /3G,例如:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /3G

5. 如果必有必要,不要啓動java虛擬機,採用matlab -nojvm啓動 (在快捷方式屬性裏面的 "..../matlab.exe") 改爲("...../matlab.exe" - nojvm)

6. 關閉Matlab Server

7. Windows中字體、窗口等都是要佔用系統資源的,所以在Matlab運行時儘量不要打開不用的窗口。

除此以外,更關鍵的是需要弄清楚以下幾個問題:

問題一:Matlab是如何存儲矩陣的?
Matlab中矩陣是以Block,也就是塊的形式存儲的。也就是說,當Matlab在爲即將存儲的矩陣劃分塊時,如果沒有相應大小的連續內存,即使實際內存沒有被完全使用,它還是會報告“Out of Memory”。

問題二:如何高效使用Memory?
Matlab 中數組必須佔用連續分配的內存段,當無法爲新建的數組分配連續的內存段的時候,”Out of Memory” 就會出現。在使用的過程中,由於存儲單元的不斷的被分配和清除,反覆分配和釋放數組會使內存被分割成不連續的區域,可用的連續內存段減少,很容易造成“Out of Memory”。因此當 Matlab 剛剛啓動時其連續內存最多,此時往往可以新建非常大的數組,這一點可以用命令 feature(’memstats’)(在 7.0 版本以上)看出。如果現實的最大連續內存段很小,但實際可用內存(非連續的)仍舊很多,則表明內存中碎片太多了。此時可以考慮用 pack 命令,pack 命令的作用就是將所有內存中的數組寫入硬盤,然後重新建立這些數組,以減少內存碎片。此外,在命令行或者程序中都可以使用 clear 命令,隨時減少不必要的內存。

因此,治本的方法如下:

1. 在命令行輸入 pack 整理內存空間

當內存被分爲很多碎片以後,其實本身可能有很大的空間,只是沒有作構的連續空間即大的Block而已。如果此時Out of Memory,此時使用pack命令可以很好的解決此問題。

2. 使用稀疏矩陣或將矩陣轉化成稀疏形式 sparse

如果矩陣中有大量的0,最好存儲成稀疏形式。稀疏形式的矩陣使用內存更少,執行時間更短。例如:
000×1000的矩陣X,它2/3的元素爲0,使用兩種存儲方法的比較:

Name
Size
Bytes
Class

X
1000x1000
8000000
double array

Y
1000x1000
4004000
double array (sparse)

3. 儘量避免產生大的瞬時變量,把沒必要的變量clear掉或當它們不用的時候應該及時clear。

4. 減少變量,儘量的重複使用變量(跟不用的clear掉一個意思)。

5. 把有用的變量先save,後clear 掉,需要時再讀出來。

下面介紹一下關於clear、save、load的特殊用法,這對在for或while等多重循環裏出現out of memory非常有效。

for k = 1:N    % N爲循環次數
% ---------------------
    var0 = k; % 獲得變量var0                        
%----------------------
    string = [sprintf('var_%d', k) ' = var0;' ];
    eval_r(string);                                                          % 等價於 var_k = var0;
    save(sprintf('var_%d.mat', k), sprintf('var_%d')); % 等價於 save var_k.mat var_k
    clear(sprintf('var_%d'));                                        % 等價於 clear var_k
end

如果要讀取剛纔存取的變量var_k, (k = 1,2, ..., N). 那麼,可以使用如下用法:

for k = 1:N
       load(sprintf('var_%d.mat', k));     % 等價於 load var_k.mat    k = 1,2, ..., N
end

另外,還有一些非常有用的用法。如果用清除剛纔讀取的變量 var_k, k = 1, 2, ..., N

clear '-regexp' '^var_'     % 清除所有以“ var_ ”開頭的變量

還有很多關於save、clear、load等用法,具體help一下。

6. 使用單精度 single 短整數替代雙精度 double

Matlab 默認的數字類型是雙精度浮點數 (double),每個雙浮點數佔用 8 個字節。對於一些整數操作來說,使用雙浮點數顯得很浪費。在 Matlab 中可以在預先分配數組時指定使用的數字類型如以下命令:zero(10, 10, ‘uint8′) 。對於浮點數,在很多精度要求不高的情況下,可以使用4個字節的單浮點數 (single),可以減少一半的內存。關於單、雙浮點數的精度對照如下,以便根據需要選擇使用:
single: 精度 (1.1921e-007) 最大數 (3.4028e+038)
double: 精度 (2.2204e-016) 最大數 (1.7977e+308)

7. 爲矩陣變量預製內存而不是動態分配

在動態分配的過程中,由於開始Matlab所用的Block隨着矩陣的增大而連續的爲此矩陣分配內存,但是由於Block的不連續性,很有可能最開始分配的Block不能滿足存儲的需要,Matlab只好移動此Block以找到更大的Block來存儲,這樣在移動的過程中不但佔用了大量的時間,而且很有可能它找不到更大的塊,導致Out of Memory。而當你爲矩陣變量預製內存時,Matlab會在計算開始前一次性找到最合適的Block,此時就不用爲變量連續的分配內存。比較下面兩個程序:

for k = 2:1000
    x(k) = x(k-1) + 5;
end

x = zeros(1, 1000);
for k = 2:1000
    x(k) = x(k-1) + 5;
end

顯然,第二個更好!!!最好的方法是,在程序一開始就位所有大的矩陣變量預製存存儲單元!!!

8. 儘量早的爲大的矩陣變量預製內存

Matlab使用heap method管理內存。當在Matlab heap中沒有足夠的內存使用時,它會向系統請求內存。但是隻要內存碎片可以存下當前的變量,Matlab會重新使用內存。比如:

a = rand(1e6,1);
b = rand(1e6,1);
使用大約15.4 MB RAM

c = rand(2.1e6,1);
使用近似16.4 MB RAM

a = rand(1e6,1);
b = rand(1e6,1);
clear
c = rand(2.1e6,1);
使用32.4 MB RAM

Matlab不能使用a、b被clear的空間,因爲它們均小於2.1 MB,而同時它們也很可能是不連續的。最好的方法:

c = rand(2.1e6,1);
clear
a = rand(1e6,1);
b = rand(1e6,1);
使用16.4 MB RAM

9. 如果可行的話,將一個大的矩陣劃分爲幾個小的矩陣,這樣每一次使用的內存減少。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章