25

while ループの結果を出力できる 2 つの列を持つ可変長のゼロ行列を設定しようとしています (これを使用して、調整された時間ステップでオイラー法からのステップ データを格納することを意図しています)。長さは、ループの反復回数によって決まります。

ループの実行中にこれを行う方法があるかどうか、または最初に設定する必要があるかどうか、およびそれを行う方法があるかどうか疑問に思っています。

4

4 に答える 4

47

スペース効率を維持しながらパフォーマンスを考慮したもう 1 つのアプローチは、必要に応じてバッチを追加して、大きなバッチでメモリを事前に割り当てることです。これは、事前にいくつのアイテムを追加するかを知らずに多数のアイテムを追加する必要がある場合に適しています。

BLOCK_SIZE = 2000;                          % initial capacity (& increment size)
listSize = BLOCK_SIZE;                      % current list capacity
list = zeros(listSize, 2);                  % actual list
listPtr = 1;                                % pointer to last free position

while rand<1-1e-5                           % (around 1e5 iterations on avrg)
  % push items on list
  list(listPtr,:) = [rand rand];            % store new item
  listPtr = listPtr + 1;                    % increment position pointer

  % add new block of memory if needed
  if( listPtr+(BLOCK_SIZE/10) > listSize )  % less than 10%*BLOCK_SIZE free slots
    listSize = listSize + BLOCK_SIZE;       % add new BLOCK_SIZE slots
    list(listPtr+1:listSize,:) = 0;
  end
end
list(listPtr:end,:) = [];                   % remove unused slots

編集: 時間比較として、次のケースを検討してください。

  1. 上記と同じコードを 50000 回繰り返します。
  2. 事前にマトリックス全体を事前に割り当てます。list = zeros(50000,2); list(k,:) = [x y];
  3. ベクトルを行列に動的に追加する:list = []; list(k,:) = [x y];

私のマシンでは、結果は次のとおりです。

1) 経過時間は0.080214 秒です。
2) 経過時間は 0.065513 秒です。
3) 経過時間は 24.433315 秒です。


アップデート:

コメントでの議論に従って、最新の R2014b リリースを使用していくつかのテストを再実行しました。結論として、最近のバージョンの MATLAB では、自動配列拡張のパフォーマンスが大幅に向上しています。

ただし、落とし穴があります。配列は、最後の次元 (2D 行列の場合は列) にわたって成長している必要があります。そのため、最初に意図したように行を追加しても、事前割り当てなしではまだ遅すぎます。これは、上記の提案されたソリューションが本当に役立つ場所です (配列をバッチで拡張することにより)。

テストの完全なセットについては、こちらを参照してください: https://gist.github.com/amroamroamro/0f104986796f2e0aa618

于 2009-10-10T21:15:27.570 に答える
15

列の数が固定されている場合は、いつでも行列に行を追加できます (ループ内)。

例えば

while (....)
   .....
   new_row =[x y] ; % new row with values x & y
   mat = [mat ; new_row]; 

もちろん、while ループの前の反復回数がわかっている場合は、行列を事前に割り当てる方が効率的です。

于 2009-10-10T14:44:18.093 に答える
7

MATLAB は、自動メモリ管理による動的型付けを使用します。つまり、行列を使用する前に固定サイズの行列を宣言する必要はありません。必要に応じて変更でき、MATLAB がメモリを動的に割り当てます。

ただし、最初に行列にメモリを割り当ててから使用するがはるかに効率的です。しかし、プログラムにこの種の柔軟性が必要な場合は、それを選択してください。

マトリックスに行を追加し続ける必要があると思います。次のコードは機能するはずです。

Matrix = [];

while size(Matrix,1) <= 10
    Matrix = [Matrix;rand(1,2)];
end

disp(Matrix);

ここではMatrix、新しい行を追加するたびに必要なスペースを動的に再割り当てしています。たとえば、行数の上限が事前にわかっている場合は、各行を宣言Matrix = zeros(20,2)して、行列に段階的に挿入できます。

% Allocate space using the upper bound of rows (20)
Matrix = zeros(20,2);
k = 1;
for k = 1:10
   Matrix(k,:) = rand(1,2);
end
% Remove the rest of the dummy rows
Matrix(k+1:end,:) = [];
于 2009-10-10T14:41:04.263 に答える
4

ジェイコブが投稿した同じものの別のフレーバー。

for counter = 1:10
    Matrix(counter,:) = rand(1,2);
end
disp(Matrix);

これの「良い」点の 1 つは、パフォーマンスを向上させるために最小サイズを推測できることです。

これも興味深いかもしれません: http://www.mathworks.com/help/matlab/math/resizing-and-reshaping-matrices.html#f1-88760

于 2009-10-10T14:48:38.193 に答える