我在 C 中有以下代码:
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
a[b[i]][c[j]]+=1;
}
}
有没有办法在 Matlab 中编写而不使用 for 循环?我的意思是使用 (:) 更快的 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;
}
}
有没有办法在 Matlab 中编写而不使用 for 循环?我的意思是使用 (:) 更快的 Matlab 方式。
类似的东西a(b(:),c(:))=a(b(:),c(:))+1
给了我内存不足的错误。
有趣的。 虽然我(还)没有为您提供解决方案(底部的解决方案),但我有一些注释和指示:
1. 内存不足错误是因为您在右侧 ( a(b(:),c(:))+1
) 创建了一个 512*256 x 512*256 元素的临时矩阵。那是 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)
,您选择的是行 (1,5,4) 和列 (3,4,5)对于每一行!
>> 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) 中存在的所有索引加一。没有更多了。将其矢量化需要一些创造性思维。使用较小的数组来查看发生了什么:
>> 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;
假设您有以下矩阵:
a = zeros(256); % or initialized with other values
b = randi(256, [512 256]);
c = randi(256, [512 256]);
这是一个更快的矢量化解决方案:
a = a + sparse(b,c,1,size(a,1),size(a,2));
这是另一个:
a = a + accumarray([b(:) c(:)], 1, size(a));
回答:是的。
a(b, c) = a(b, c) + 1;
例子:
>> a = zeros(5);
>> b = [1,3];
>> c = [2,4,5];
>> a(b,c) = a(b,c) + 1;
>> a
a =
0 1 0 1 1
0 0 0 0 0
0 1 0 1 1
0 0 0 0 0
0 0 0 0 0