4

この質問によると、PreallocationisMatlabを使用してみる必要があります。

現在、事前に割り当てる行列の正確なサイズを計算できない状況があります。サイズがわかります。

行列の実際のサイズが100であると仮定しますが、私にはわかりません。Sh

どのシナリオがより効率的ですか:

  1. 私は贅沢にすべきですか?私は大きな行列を推測し、最後に余分な行を削除します。
  2. 私はけちである必要がありますか?サイズが小さいと思いますが、間違っていた場合は、新しい行を追加します。

ありがとう。

4

3 に答える 3

3

私の意見では、答えは@natanによって描かれるよりも少し複雑です。彼の答えが考慮に入れていない2つの要因があると思います:

  1. 必要なメモリのコピーの可能性:マトリックスサイズを過小評価して再割り当てする場合は、古い値をすべて新しい割り当て場所にコピーする必要があります。

  2. メモリチャンクの継続性:Matlabは、古いマトリックスの最後に新しいメモリを継続的に割り当てることができる場合があります。原則として、このようなシナリオでは、古い値を新しい場所にコピーする必要はありません。これは、古い値と同じであるためです。ただし、2D行列にを追加する場合、Matlabは行列を行を中心にメモリに格納するため、このシナリオでもコンテンツをコピーする必要があります。

だから、私の答えはこれです:

まず、行列のサイズについて正確にわからないことです。1つの次元がわかっている場合は、行列の行数にするだけで、列数を変更するだけで済みます。このように、すでに保存されているデータをコピーする必要がある場合は、より大きなチャンクでコピーされます。

第二に、それはあなたが自由に使えるRAMの空き容量に依存します。RAMが不足していなければ、過大評価しても問題はありません。

ただし、RAMが不足している場合は、見積もりを控えることを検討してください。ただし、再割り当てする場合は、反復ごとに新しいブロックサイズを増やしてください。

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
于 2012-12-27T07:31:02.733 に答える
2

他の教育的な答えに加えて、短い短いバージョン:3つのケースがあります:

  1. 配列のサイズは比較的小さい(最大数千バイト)->実際には問題ではありません。
  2. 配列は大きいですが、システムにあるメモリの量に制限されません->過大評価。
  3. 配列は大きく、システムにあるメモリの量に制限されます->Shaiが提案したことを実行します。
于 2012-12-27T08:48:36.943 に答える
2

興味深い質問には+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の詳細な回答を参照してください...

于 2012-12-27T06:22:59.777 に答える