Matlab预分配,猜一个大矩阵还是一个小矩阵?

Matlab预分配,猜一个大矩阵还是一个小矩阵?,matlab,memory-management,matrix,Matlab,Memory Management,Matrix,根据这一点,我应该尝试使用预分配是Matlab 现在我遇到了一种情况,我无法计算要预分配的矩阵的确切大小。我能猜出尺寸 假设矩阵的实际大小是100,但我不知道。嘘 哪种方案更有效: 我应该奢侈吗?我猜是一个大矩阵,最后我删除了额外的行 我应该小气点吗?我猜是一个小尺寸,如果它是错误的,我会添加新的行 谢谢。+1回答这个有趣的问题 编辑答案: 从一开始的一个小实验研究来看,以后再添加行似乎更好,但现在,当您拥有正确大小的信息时,过度激活和重新预分配似乎更有效。我从矩阵大小3000开始,猜测大小估计

根据这一点,我应该尝试使用预分配是Matlab

现在我遇到了一种情况,我无法计算要预分配的矩阵的确切大小。我能猜出尺寸

假设矩阵的实际大小是100,但我不知道。嘘

哪种方案更有效:

  • 我应该奢侈吗?我猜是一个大矩阵,最后我删除了额外的行
  • 我应该小气点吗?我猜是一个小尺寸,如果它是错误的,我会添加新的行

  • 谢谢。

    +1回答这个有趣的问题

    编辑答案: 从一开始的一个小实验研究来看,以后再添加行似乎更好,但现在,当您拥有正确大小的信息时,过度激活和重新预分配似乎更有效。我从矩阵大小3000开始,猜测大小估计的误差为10%,如下所示:

        clear all
        clc
        guess_size=3000;
        m=zeros(guess_size);
        %1. oops overesrimated, take out rows
        tic
        m(end-300:end,:)=[];
        toc
    
        %1b. oops overesrimated,  preallocate again
        tic
        m=zeros(guess_size-300,guess_size);
        toc
    
        %2. oops overesrimated, take out cols
        m=zeros(guess_size);
        tic
        m(:,end-300:end)=[];
        toc
    
        %2b. oops overesrimated,  preallocate again
        m=zeros(guess_size);
        tic
        m=zeros(guess_size,guess_size-300);
        toc
    
        %3. oops underesrimated, add rows
        m=zeros(guess_size);
        tic
        m=zeros(guess_size+300,guess_size);
        toc
    
        %4. oops underesrimated, add cols
        m=zeros(guess_size);
        tic
        m=zeros(guess_size,guess_size+300);
        toc
    
    Elapsed time is 0.041893 seconds.
    Elapsed time is 0.026925 seconds.
    Elapsed time is 0.041818 seconds.
    Elapsed time is 0.023425 seconds.
    Elapsed time is 0.027523 seconds.
    Elapsed time is 0.029509 seconds.
    

    选项2b和1b比低估略快,因此如果可以,最好高估,然后再次预分配。从数组中删除行永远不会有效。此外,添加列似乎效率略高,但这只是一项快速而肮脏的工作。参见@Shai内部工作的详细答案…

    我认为,答案比@natan描述的要复杂一些。 我认为他的回答没有考虑到两个因素:

  • 可能需要的内存副本:当您低估矩阵大小并重新分配它时,它的所有旧值都应复制到新分配的位置

  • 内存块的连续性:有时Matlab能够在旧矩阵的末尾连续分配新内存。原则上,在这种情况下,旧值不需要复制到新位置,因为它与旧值相同,只是更大而已但是,如果将添加到2D矩阵,则即使在这种情况下,也需要复制内容,因为Matlab在内存中以行主方式存储矩阵

  • 所以,我的答案是:

    首先,关于矩阵的大小,你到底不知道什么:如果你知道一个维度,就把它设为矩阵的行数,这样你就只需要更改列数。这样,如果您已经存储的数据需要复制,它将以更大的块进行复制

    第二,这取决于你有多少空闲内存供你使用。 如果你不缺乏RAM,那么高估也没什么错

    但是,如果你在RAM中短,考虑下估计。strong>但是重新分配时,在每次迭代时增加新块大小:

    BASIC_SIZE = X;  % first estimate
    NEW_SIZE = Y;    % if need more, add this amount
    factor = 2;      
    arr = zeros( m, BASIC_SIZE ); % first allocation, assuming we know number of rows
    while someCondition
        % process arr ...
        if needMoreCols
            arr(:, size(arr,2) + (1:NEW_SIZE) ) = 0; % allocate another block
            NEW_SIZE = round(NEW_SIZE * factor);  % it seems like we are off in estimation, try larger chunk next time factor should be > 1
        end
    end
    arr = arr(:, 1:actualNumOfCols ); % resize to actual size, discard unnecessary columns
    

    除其他教育性答案外,简短版本: 有三种情况:

  • 数组的大小相对较小(最多一千字节)->这并不重要
  • 数组很大,但您不受系统内存量的限制->高估
  • 数组很大,并且受系统内存量的限制->按照Shai的建议执行

  • +1对于这个详细的答案,我认为有几个因素没有考虑到,可能会产生重大影响。请看我的答案了解更多细节。你的实验只分配了新的空间。它们不考虑Matlab需要将旧的小数据复制到新的分配空间的情况。新的分配应该类似于
    m=cat(1,m,零(300,猜测大小);
    (示例3)。