单元阵列广播求和-MATLAB
假设我有一个矩阵,如下所示:单元阵列广播求和-MATLAB,matlab,vectorization,cell-array,Matlab,Vectorization,Cell Array,假设我有一个矩阵,如下所示: C1=nx2单元每个单元都是[5x5双精度] C2=1x1单元包含一个[5x5双精度] 如何将C3计算为: C3{1,1} = C1{1,1}+C2{1,1}; C3{1,2} = C1{1,2}+C2{1,1}; . . C3{n,2} = C1{n,2}+C2{1,1}; 使用cellfun或任何其他不循环的方法对于具有规则大小数组的情况,最好使用多维数组,而不是慢速单元格数组。尽管如此,还是坚持使用单元数组,这里
C1=nx2单元
每个单元都是[5x5双精度]
C2=1x1单元
包含一个[5x5双精度]
如何将C3
计算为:
C3{1,1} = C1{1,1}+C2{1,1};
C3{1,2} = C1{1,2}+C2{1,1};
.
.
C3{n,2} = C1{n,2}+C2{1,1};
使用
cellfun
或任何其他不循环的方法对于具有规则大小数组的情况,最好使用多维数组,而不是慢速单元格数组。尽管如此,还是坚持使用单元数组,这里有一个向量化的解决方案,在将它们转换为多维数组之后,它将用作向量化广播求和的基础-
%// Store size of each cell and size of C1 for later reshaping purposes
[m,n] = size(C1{1,1})
[nr,nc] = size(C1);
%// Perform broadcasted summations with BSXFUN
sums = bsxfun(@plus,cat(3,C1{:}),C2{1,1})
%// Reshape and convert back to cell arrays as desired output
out = reshape(mat2cell(sums,m,n,ones(1,nr*nc)),nr,nc)
对于具有规则大小数组的情况,最好使用多维数组,而不是慢速单元数组。尽管如此,还是坚持使用单元数组,这里有一个向量化的解决方案,在将它们转换为多维数组之后,它将用作向量化广播求和的基础-
%// Store size of each cell and size of C1 for later reshaping purposes
[m,n] = size(C1{1,1})
[nr,nc] = size(C1);
%// Perform broadcasted summations with BSXFUN
sums = bsxfun(@plus,cat(3,C1{:}),C2{1,1})
%// Reshape and convert back to cell arrays as desired output
out = reshape(mat2cell(sums,m,n,ones(1,nr*nc)),nr,nc)
直接使用可以实现您想要的功能:
C3 = cellfun(@(x) x+C2{1,1},C1,'uniformoutput',false);
这将基本上在单元数组的每个元素上循环C1
,并为每个元素应用匿名函数@(x)x+C2{1,1}
,即每个元素将被添加到C2{1,1}
。结果元素以与C1
大小相同的单元格数组返回
对于一些较小的测试用例,我比较了这个解决方案和那个解决方案。结果并非微不足道,因为
cellfun
和cat
(用于Divakar的解决方案)的速度都非常慢。我加入了第三个版本进行检查,其中我在匿名函数中定义了一个临时变量:
tmpvar=C2{1,1};
C3a2=cellfun(@(x) x+tmpvar,C1,'uniformoutput',false);
这背后的基本原理是,访问单个单元格元素应该有一些开销,我不确定整个单元格是否被拉入匿名函数的工作区
我定义了一个单独的函数来测试这三种情况,以便让JIT完成它的工作(但请注意,我使用的是R2012b,一个更新的版本可能会给出完全不同的结果,但需要注意)。我在相同的随机输入上运行所有三个案例(使用大小为C2
的单元格数组[1,1]
,并包含与C1{k,l}
大小相同的数组),从10次尝试中选择最短的运行时间(基于tic/toc
)
5x5
矩阵的10x10
单元阵列:
:cellfun
0.000452s
+cellfun
:tmpvar
0.000287s
:bsxfun(cat)
0.002970 s
5x5
矩阵的100x100
单元阵列:
:cellfun
0.000988 s
+cellfun
:tmpvar
0.000963s
:bsxfun(cat)
0.004661 s
10x10
矩阵的5x5
单元阵列:
:cellfun
0.001580s
+cellfun
:tmpvar
0.000945s
:bsxfun(cat)
0.011358 s
100x100
矩阵的单元阵列5x5
矩阵:
:cellfun
0.108276s
+cellfun
:tmpvar
0.082675 s
:bsxfun(cat)
1.132417s
cellfun
的匿名函数中使用临时变量确实可以计数,这是有意义的(因为该函数的计算次数较大)bsxfun(cat)
的解决方案对于小单元阵列稍微慢一点,对于大单元阵列则慢得多。我怀疑cat
是罪魁祸首:cat
需要花很多时间才能把额外的维度放在一起。我甚至可以想象,使用带有预分配的循环可能比cat
更好n>1000
)矩阵和单元数组,检查相同的情况会很有趣C3 = cellfun(@(x) x+C2{1,1},C1,'uniformoutput',false);
这将基本上在单元数组的每个元素上循环C1
,并为每个元素应用匿名函数@(x)x+C2{1,1}
,即每个元素将被添加到C2{1,1}
。结果元素以与C1
大小相同的单元格数组返回
对于一些较小的测试用例,我比较了这个解决方案和那个解决方案。结果并非微不足道,因为
cellfun
和cat
(用于Divakar的解决方案)的速度都非常慢。我加入了第三个版本进行检查,其中我在匿名函数中定义了一个临时变量:
tmpvar=C2{1,1};
C3a2=cellfun(@(x) x+tmpvar,C1,'uniformoutput',false);
这背后的基本原理是,访问单个单元格元素应该有一些开销,我不确定整个单元格是否被拉入匿名函数的工作区
我定义了一个单独的函数来测试这三种情况,以便让JIT完成它的工作(但请注意,我使用的是R2012b,一个更新的版本可能会给出完全不同的结果,但需要注意)。我在相同的随机输入上运行所有三个案例(使用大小为C2
的单元格数组[1,1]
,并包含与C1{k,l}
大小相同的数组),从10次尝试中选择最短的运行时间(基于tic/toc
)
5x5
矩阵的10x10
单元阵列:
:cellfun
0.000452s
+cellfun
:tmpvar
0.000287s
:bsxfun(cat)
0.002970 s
5x5
矩阵的100x100
单元阵列:
:cellfun
0.000988 s
-