我需要在Matlab中总结一个密集和稀疏的向量,以及实现它的天真方式,即:
w = rand(1e7,1);
d = sprand(1e7,1,.001);
tic
for k = 1 : 100
w = w + d;
end
toc
需要大约3.5秒,这比我期待Matlab在引擎盖后面实现它的方式慢大约20倍:
for k = 1 : 100
ind = find(d);
w(ind) = w(ind) + d(ind);
end
(当然这个更快版本的时间取决于稀疏性)。
那么,为什么Matlab没有这样做?快速的方式'?我到目前为止使用Matlab的经验表明它在利用稀疏性方面相当不错。
更重要的是,还有其他稀疏的'操作我应该怀疑效率不高?
答案 0 :(得分:1)
我肯定不知道答案,但我会猜测你发生了什么。我不了解Fortran,但从C ++的角度来看,你所展示的内容是有道理的,我们只需要解构那个陈述。
其中a = b + c
已满且a,b
稀疏的c
的伪代码转换看起来像a.operator= ( b.operator+ (c) )
。
Matlab中的完整矩阵容器很可能应该有专门的算术运算符来处理稀疏输入,即full full::operator+ ( const sparse& )
之类的东西。这里需要注意的主要问题是混合完全/稀疏算术运算的结果必须是满的。因此,即使没有更新的值,我们也需要创建一个新的完整容器来存储结果。
[ 注意:返回的完整容器是一个临时容器,因此作业a.operator= ( ... )
可能会避免使用完整的附加副本,例如使用full& full::operator= ( full&& )
。的 强>
不幸的是,由于Matlab中没有算术复合操作(即operator +=
),因此无法返回新的完整容器。这就是为什么Matlab无法利用在您的示例中a
与b
相同的事实(尝试用x = w + d
计算循环时间,没有运行时差异),这就是IMO的开销。
[ 注意:即使没有明确的分配,例如b+c;
,也会分配通用答案变量ans
。的 强>
有趣的是,full full::operator+ ( const sparse& )
和full sparse::operator+ ( const full& )
之间似乎存在显着差异,即a = b + c
和a = c + b
之间;我无法详细说明原因,但后者似乎更快。
无论如何,我的简短回答是#34;因为Matlab没有算术复合算子",这是不幸的。如果你知道你将要做很多这些操作,那么实现 ad hoc 优化版本(如你提议的那个)并不是很难。希望这有帮助!