【问题标题】:Can you preallocate an array of random size?你可以预先分配一个随机大小的数组吗?
【发布时间】:2019-03-19 05:02:14
【问题描述】:

相关代码的基本部分可以提炼成:

list=rand(1,x); % where x is some arbitrarily large integer
hitlist=[];
for n=1:1:x
    if rand(1) < list(n)
        hitlist=[hitlist n];
    end
end
list(hitlist)=[];

这个程序运行得很慢,我怀疑这就是原因,但我不知道如何修复它。 hitlist 的长度必然会以随机方式变化,因此我不能简单地预先分配适当大小的“零”。我打算将hitlist 和zeros 设置为列表的长度,但随后我将不得不删除所有多余的零,而且我不知道如何做到这一点而不会遇到同样的问题。

如何预分配随机大小的数组?

【问题讨论】:

    标签: arrays matlab pre-allocation


    【解决方案1】:

    我不确定预分配“随机大小”,但您可以预分配大块,例如1e3,或者对您的用例有用:

    list=rand(1,x); % where x is some arbitrarily large integer
    a = 1e3; % Increment of preallocation
    hitlist=zeros(1,a);
    k=1; % counter
    for n=1:1:x
        if rand(1) < list(n)
            hitlist(k) = n;
            k=k+1;
        end
        if mod(k-1,a)==0 % if a has been reached
            hitlist = [hitlist zeros(1,a)]; % extend
        end
    end
    hitlist = hitlist(1:k-1); % trim excess
    % hitlist(k:end) = []; % alternative trim, but might error
    list(hitlist)=[];
    

    这不会是最快的,但至少比每次迭代递增快很多。确保选择a合适;您甚至可以使用memory 以某种方式基于可用的 RAM 量,然后修剪多余的部分,这样您就根本不需要执行循环内的技巧。


    顺便说一句:MATLAB 以列为主,因此以这种方式运行矩阵更快。 IE。首先是第一列,然后是第二列,依此类推。对于一维数组,这无关紧要,但对于矩阵,它确实如此。因此我更喜欢使用list = rand(x,1),即作为列。

    对于这种特定情况,无论如何都不要使用这种循环方法,而是使用logical indexing:

    list = rand(x,1);
    list = list(list<rand(size(list)));
    

    【讨论】:

    • 我不相信以块为单位递增数组是要走的路。您所做的只是可能减慢 JIT。当您执行hitlist(end+1)=n 时,MATLAB 会将分配给数组的内存加倍(数组大小 ~= 分配大小)。逐块执行此操作不会让 MATLAB 优化此用例。问题在于hitlist = [hitlist n],因为在那里你没有扩展数组而是创建一个新数组。我在某处有一个问答链接可以证明这一点,我会去寻找它。
    • Here it is。阅读问题和我的答案以查看完整的实验。
    • 但是对于逻辑索引建议还是 +1。这是正确的方法。
    • 我会在这里公开吃我的话。您以 1e3 为步长递增数组的方法比将数组递增 hitlist(end+1)=n 稍快。任何一种方法都比 OP 的代码快一个数量级。当然,最后的版本没有循环,再次比增加数组大小的两种快速方法中的任何一种快两个数量级。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 2023-04-10
    相关资源
    最近更新 更多