【问题标题】:Summation of dense and sparse vectors密集和稀疏向量的总和
【发布时间】:2015-05-11 01:23:16
【问题描述】:

我需要在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 的经验表明它非常擅长利用稀疏性。

更重要的是,是否还有其他我应该怀疑效率不高的“稀疏”操作?

【问题讨论】:

  • 一些猜测:您的方法之所以有效,是因为等式两边都有w;它不适用于x = w + d。也许 Matlab 根本没有实现用于识别稀疏累积的优化过程。
  • 您是否测试过在单独的 m 文件中运行它?这对 JIT 可能很重要,在某些情况下,它足够聪明地找出 w = w + d 是一个就地操作,而在命令行上它可能会创建一个新向量 w,同时丢弃旧向量。 ..
  • @OliverCharlesworth:您对实施的看法可能是正确的;但是我认为我的用例很常见,例如梯度下降更新规则。
  • @BasSwinckels:从 m 文件运行结果是一样的。

标签: matlab sparse-matrix


【解决方案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 之间;我不能说更多关于为什么会这样,但后者似乎更快。

无论如何,我的简短回答是“因为 Matlab 没有算术复合运算符”,这很不幸。但是,如果您知道您将经常执行这些操作,那么实施像您建议的那样ad hoc 优化的版本应该不会太难。希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2013-07-28
    • 2015-10-09
    • 2018-12-25
    • 2020-05-22
    • 2021-12-18
    • 2014-01-31
    • 2013-08-27
    • 1970-01-01
    • 2013-02-16
    相关资源
    最近更新 更多