私はCで次のコードを持っています:
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
a[b[i]][c[j]]+=1;
}
}
forループを使わずにMatlabでこれを書く方法はありますか? (:) を使用した Matlab の方法の方が高速です。
a(b(:),c(:))=a(b(:),c(:))+1
メモリ不足エラーが発生するようなものです。
私はCで次のコードを持っています:
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
a[b[i]][c[j]]+=1;
}
}
forループを使わずにMatlabでこれを書く方法はありますか? (:) を使用した Matlab の方法の方が高速です。
a(b(:),c(:))=a(b(:),c(:))+1
メモリ不足エラーが発生するようなものです。
面白い。 私は(まだ)あなたのための解決策を持っていませんが(解決策は一番下にあります)、いくつかのメモとポインタがあります:
1. メモリ不足エラーは、右側に 512*256 x 512*256 要素の一時行列を作成しているためです ( a(b(:),c(:))+1
)。つまり、2^34 バイト — 17GB です! そのため、メモリ不足エラーが発生しています。また、この配列はあなたが望むものでさえないことに注意してください! この例を見てください:
>> a = magic(5);
>> b = [1 5 4]; % The rows that contain the numbers 1,2,3 respectively
>> c = [3 4 5]; % The columns that contain ^ ...
今、a(1,3) == 1、a(5,4) == 2 などa(b,c)
。それらの行のすべてに対して!
>> a(b,c)
ans =
1 8 15
25 2 9
19 21 3
あなたが気にするのは対角線だけです。解決策は、sub2indを使用して添字ペアを線形インデックスに変換することです。
>> a(sub2ind(size(a),b,c))
ans =
1 2 3
2. あなたが提案した解決策も、あなたが望んでいることにはなりません。Matlab にはインクリメント演算子がないため、(b,c) に存在するすべてのインデックスを 1 ずつインクリメントするだけです。そしてもうありません。これをベクトル化するには、創造的な思考が必要です。小さい配列を使用して、何が起こっているかを確認します。
>> a = zeros(4,4);
>> b = ones(8,4);
>> c = ones(8,4);
>> a(b,c) = a(b,c) + 1;
>> a
a =
1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
編集どうぞ!ベクトル化されたインクリメント:
>> idxs = sub2ind(size(a),b(:),c(:)); % convert subscripts to linear indices
>> [unique_idxs,~,ic] = unique(idxs); % Get the unique indices and their locations
>> increment_counts = histc(ic,1:max(ic)); % Get the number of occurrences of each idx
>> a(unique_idxs) = a(unique_idxs) + increment_counts;