2012-02-13 48 views
5

因此,當您對尺寸要求有一個粗略的瞭解時,reserve非常有用。有誰知道類似的方法來預分配MATLAB中的數組?在MATLAB中預先分配內存àla std :: vector :: reserve(n)

我不是在哈克(但有效)的方法,如下面很感興趣:

x = zeros(1000,1); 
for i = 1:10000 
    if i > numel(x) 
     x = [x;zeros(size(x))]; 
    end 
    x(i) = rand; 
end 
x(i+1:end) = []; 
+2

你可能會覺得這個答案有幫助:http://stackoverflow.com/a/1549094/97160 – Amro 2012-02-13 17:08:57

+0

@Amro:是的,好的答案一如既往。但是我希望有一些「魔術」MATLAB函數我忽略了。 – Jacob 2012-02-13 17:29:15

回答

3

的「哈克」的方法是做它的唯一途徑。但是,您不需要檢查我< = numel(x)。該陣列將被自動擴大(但沒有加倍數組):

x = zeros(1000,1); 
for i = 1:10000 
    x(i) = rand; 
end 
x(i+1:end) = []; 

編輯:爲了保持它的簡單,同時仍保留數組加倍,你可以寫一個類,或者簡單的幾個輔助功能(如下圖)。

編輯2:與手動黑客相比,輔助函數的使用會減慢速度。在MATLAB 2010中,它比天真的增長速度還要快。在MATLAB 2011中,天真的方法實際上更快,這表明此版本具有更智能的分配。也許它足夠快,所以根本不需要破解。感謝Andrew Janke指出這一點。

function listtest() 
    n = 10000; 
    l = new_list(); 
    for i=1:n 
     l = list_append(l, i); 
    end 
    a = list_to_array(l); 
end 

function l = new_list() 
    l = [0 0]; 
end 
function l = list_append(l, e) 
    if l(1)+1 == length(l) 
     l(length(l)*2) = 0; 
    end 
    l(1) = l(1)+1; 
    l(l(1)+1) = e; 
end 
function a = list_to_array(l) 
    a = l(2:1+l(1)); 
end 

EDIT(從AndrewJanke)

這裏的代碼比較實現的速度。

function manual_reserve_example(n) 
x = zeros(1000,1); 
for i = 1:n 
    if i > numel(x) 
     x = [x;zeros(size(x))]; 
    end 
    x(i) = i; 
end 
x(i+1:end) = []; 
end 

function naive_growth(n) 
x = 0; 
for i = 1:n 
    x(i) = i; 
end 
end 

function compare_them(n) 
fprintf('Doing %d elements in Matlab R%s\n', n, version('-release')); 
tic; 
naive_growth(n); 
fprintf('%30s %.6f sec\n', 'naive_growth', toc); 
tic; 
manual_reserve_example(n); 
fprintf('%30s %.6f sec\n', 'manual_reserve', toc); 
tic; 
listtest(n); 
fprintf('%30s %.6f sec\n', 'listtest', toc); 
end 
+2

原始問題中的檢查實現了一種算法,使溢出時的分配大小加倍,從而導致'O(log(n))'重新分配(在這種情況下爲4)。 Matlab的自然增長一次只增長一個元素,在這個例子中重新分配9000次。 – Pursuit 2012-02-13 17:23:05

+0

@Pursuit:的確如此。這也是'保留'的作用。 – Jacob 2012-02-13 17:28:14

+0

rasmus:-1沒有。函數調用的開銷(以及JIT就地優化的可能失敗)使得這個幫助函數的實現比Jacob的手動擴展慢得多,或者甚至是天真的非預分配'x = 0;對於i = 1:n; X(I)= I;結束「代碼。你測試過了嗎?在Matlab和其他語言中,您需要考慮操作成本並實際測量您認爲是優化的代碼的性能。由於更高的開銷,製作課程會更加糟糕。 – 2012-02-13 19:58:43

0

有使用STRUCT和REPMAT命令預先分配用於在MATLAB 7.6(R2008a)的結構存儲器的方法。

實施例1:一種結構,一個場的子場

s.field1.subfield:具有兩個字段

s.field1 s.field2

s = struct('field1',cell(1),'field2',cell(1)); 

實施例2的結構

s = struct('field1',struct('subfield',cell(1))); 

示例3:結構陣列

V(1).field1 ... V(100).field1

s = struct('field1',cell(1)); 
v = repmat(s,100,1); 
+0

這不起作用。在向數據添加數據時查看使用'whos v'分配給'v'的字節數;它不是預先分配的。例如。 'whos v; v(1).field1 = 10; whos v; v(2).field1 = 20; whos v' – Jacob 2012-02-16 19:06:50

1

的乾淨的解決方案,以您所提供的例子是爲了向後迭代。

for i = 10000:-1:1 
    x(i) = rand; 
end 

這不會在最終大小實際上是未知的情況下工作,但它往往比我本來期望派上用場了我。


否則,我通常實現一個像你在原始問題中顯示的「double overflow」算法。

乾淨的解決方案是圍繞可調整的矢量調整大小算法包裝Matlab類,然後使用該類。我不知道有什麼理由不能建立這樣的班級,但我從來沒有坐下來嘗試實施班級。(我很好奇,如果一個例子已經存在的文件交換的地方。)

+0

@woodchips在這裏提出了一些實現:http://stackoverflow.com/a/3251547/ 97160 – Amro 2012-02-13 17:38:43

相關問題