2012-02-13 47 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

相关问题