1

多数の (2x1) 行列で構成されるセル配列 A があります。セル A の各要素で乗算する別の行列 B (2x2) があります。つまり、配列 A 内のすべての行列を B で乗算して、別のセル配列 C (A と同じサイズ) を生成する必要があります。 2x1 行列の。

視覚的に、

B*|A{1,1} A{1,2} ... A{1,n}| = |C{1,1} C{1,2} ... C{1,n}|
  |::::::::::::::::::::::::|   |::::::::::::::::::::::::|
  |A{m,1} A{m,2} ... A{m,n}|   |C{m,1} C{m,2} ... C{m,n}|

ここで、C{i,j}=B*A{i,j}

cellfunを使用してこれを行うと、非常に遅くなります。 明示的なループを使用せずにこれをベクトル化し、A と B のサイズに関係なく (乗算可能である限り) 操作を高速化する方法はありますか?

4

3 に答える 3

3

いくつかの方法が考えられます。まず、いくつかの偽のデータを生成します

A = cellfun(@(~)rand(2,1), cell(1000), 'uni', false);
B = rand(2);

セルファン

おっしゃるとおり、これは避けたいところです。いずれにせよ、比較のためにここに含めます。

C = cellfun(@(x)B*x, A, 'UniformOutput',false);

匿名関数が関係しているため、低速です。組み込みの文字列関数 (「参考文献」を参照) を備えた Cellfunhelp cellfunは猛威を振るっていますが、無名関数は反復ごとに強制的に実行を Matlab インタープリターに渡します。これは JIT によっていくらか効率化できますが、最適とは言えません。

セル拡張、num2cell、形状変更

アイデア: セルを 2x1000 行列に展開し、乗算を実行し、結果を正しいサイズのセル配列にキャストします。原則としてはエレガントですが、実際に使用すると少し混乱します。

C = reshape( num2cell(B*[A{:}],1), size(A) );

中間の 2x1000 テンポラリは、メモリ フットプリントの観点からは少し無駄であることに注意してください...また、パス スルーnum2cell(これは組み込みではない) と「役に立たない」reshapeため、実行がかなり遅くなります。

ループ用

ループは、最も読みやすく、実装も簡単です。メモリ使用量が少なく、JIT による高速化などに適しています。

C = cell(size(A));
for ii = 1:numel(A)        
   C{ii} = B*A{ii};        
end

唯一の欠点は、評判が悪いことです:)

比較

そして今、キッカーのために: どれが最速ですか?

tic
C = cellfun(@(x)B*x, A, 'uni',false);
toc

tic 
C = reshape( num2cell(B*[A{:}],1), size(A) );
toc

tic
C = cell(size(A));
for ii = 1:numel(A)    
    C{ii} = B*A{ii};    
end
toc

結果:

Elapsed time is 4.738791 seconds.  % cellfun
Elapsed time is 4.161515 seconds.  % cell expansion, num2cell, reshape
Elapsed time is 3.808822 seconds.  % loop

結論: R2008 で JIT コンパイルが導入されて以来、ループはもはや悪ではありません。デフォルトでそれらを回避しようとしないでください。

于 2013-04-04T12:04:46.483 に答える
0

私はこれを試してみましたが、それがあなたが探しているものであることを願っています:

clc,clear all,close all
clc,clear all,close all
A = cell(10,2);
for jj = 1:numel(A)
 A{jj} = rand(2,1);
end

B = rand(2,2);
C = cat(3,A{:});
D = cell(size(A));

for ii = 1:size(C,3)
 D{ii} = B*C(:,:,ii);
end

明示的なforループが含まれていますが (私は知っています)、最新の MATLAB リリースでは、ループの呼び出しによるパフォーマンスへの悪影響はそれほど大きくありませんfor

または、この回答をヒントとして使用できます。これが役立つことを願っています。

于 2013-04-04T11:15:27.113 に答える