2

大きな行列 M (nxm) があります。ベクトルにセル要素として格納されているインデックスで指定されたいくつかの要素を合計します。インデックスのグループが多数あるため、セルには複数の要素があります。例えば

M = rand(2103, 2030);
index{1} = [1 3 2 4 53 5 23 3];
index{2} = [2 3 1 3 23 10234 2032];
% ...
index{2032} = ...;

index{1} のすべての要素を合計し、index{2} のすべての要素を合計します ...、今はループを使用しています

sums = zeros(1, 2032);
for n=1:2032
  sums(n) = sum(M(index{n}));
end

ループの代わりに1行のコマンドを使用してそれを行う方法があるかどうか疑問に思っています。ループの使用はかなり遅いです。

4

2 に答える 2

6

おそらく古典的な使い方cellfun

sums = cellfun(@(idx) sum(M(idx)), index);

編集:これは、このアプローチが for ループよりもわずかに遅いが、Eitan T の方法よりも高速であることを示す大規模なケースのベンチマークです。

M = rand(2103, 2030);
index = cell(1, 2032);
index{1} = [1 3 2 4 53 5 23 3];
index{2} = [2 3 1 3 23 10234 2032];

for n=3:2032
    index{n} = randi(numel(M), 1, randi(10000));
end

N = 1e1;
sums = zeros(1, 2032);
tic
for kk = 1:N
    for n=1:2032
        sums(n) = sum(M(index{n}));
    end
end
toc

tic
for kk = 1:N
    sums = cellfun(@(idx) sum(M(idx)), index);
end
toc

tic
for kk = 1:N
    sums = cumsum(M([index{:}]));
    sums = diff([0, sums(cumsum(cellfun('length', index)))]);
end
toc

結果は

Elapsed time is 2.072292 seconds.
Elapsed time is 2.139882 seconds.
Elapsed time is 2.669894 seconds.
于 2013-10-02T06:55:27.273 に答える
1

おそらくワンライナーほどエレガントではありませんcellfunが、桁違いに速く実行されます。

sums = cumsum(M([index{:}]));
sums = diff([0, sums(cumsum(cellfun('length', index)))]);

大規模な入力の場合、JIT で高速化されたループよりも約 4 倍または 5 倍速く実行されます。の各セルにindex~2000 を超える要素を持つベクトルが含まれている場合、このアプローチのパフォーマンスはループ (およびcellfun) と比較して低下し始めることに注意してください。

基準

M = rand(2103, 2030);
I = ceil(numel(M) * rand(2032, 10));
index = mat2cell(I, ones(size(I, 1), 1), size(I, 2));
N = 100;

tic
for k = 1:N
    sums = zeros(1, numel(index));
    for n = 1:numel(sums)
        sums(n) = sum(M(index{n}));
    end
end
toc

tic
for k = 1:N
    sums = cellfun(@(idx) sum(M(idx)), index);
end
toc

tic
for k = 1:N
    sums = cumsum(M([index{:}]));
    sums2 = diff([0, sums(cumsum(cellfun('length', index)))]);
end
toc

これを MATLAB 2012a (2.27 GHz 16 コア Intel Xeon プロセッサで実行されている Windows Server 2008 R2) で実行すると、次の結果が得られました。

Elapsed time is 0.579783 seconds.
Elapsed time is 1.789809 seconds.
Elapsed time is 0.111455 seconds.
于 2013-10-02T08:33:10.727 に答える