【发布时间】:2018-12-06 04:54:41
【问题描述】:
我有一个相对较大的矩阵 NxN (N~20,000) 和一个 Nx1 向量,用于标识必须组合在一起的索引。
我想将矩阵的各个部分相加,原则上可以有不同数量的元素和不相邻的元素。 我很快写了一个可以正常工作的双 for 循环,但它当然效率低下。分析器将这些循环识别为我的代码中的瓶颈之一。
我试图找到一种智能矢量化方法来解决这个问题。我探索了arrayfun、cellfun 和bsxfun 函数,并寻找类似问题的解决方案……但我还没有找到最终解决方案。
这是带有两个 for 循环的测试代码:
M=rand(10); % test matrix
idxM=[1 2 2 3 4 4 4 1 4 2]; % each element indicates to which group each row/column of M belongs
nT=size(M,1);
sumM=zeros(max(idxM),max(idxM));
for t1=1:nT
for t2=1:nT
sumM(t1,t2) = sum(sum(M(idxM==t1,idxM==t2)));
end
end
【问题讨论】:
-
也许值得注意的是
arrayfun和cellfun基本上是变相的循环,很可能优化后的for循环也一样快(如果不简洁的话)。 -
感谢您指出这一点。您在答案中使用的 bsxfun 怎么样?
-
我假设您的意思是 Luis 的回答...
bsxfun是另一种野兽,通常可以提高速度(取决于它的使用方式)。将cellfun和arrayfun视为“我想遍历一个数组并对每个元素应用一个函数”,而bsxfun是“然后将这些向量扩展为等效大小执行矩阵运算” 所以不是逐个元素。它们有不同的有用应用,bsxfun适用于数组和矩阵之间的数值运算,而循环函数适用于简洁的代码,而无需初始化输出等。 -
@user9998992
bsxfun是 very fast,implicit expansion 也是如此 -
是的,同意。行:
nT=size(M,1); sumM=zeros(max(idxM),max(idxM));应与行交换:nT=max(idxM); sumM=zeros(nT,nT);(在我的原始代码中,它们是正确的,但我在测试代码中输入了拼写错误)
标签: matlab matrix vectorization bsxfun