在Julia中通过稀疏向量更新密集向量很慢

时间:2016-04-17 07:45:13

标签: julia sparse-matrix

我正在使用Julia版本0.4.5,我遇到以下问题: 据我所知,在稀疏矢量和密集矢量之间取内积应该与用稀疏矢量更新密集矢量一样快。后者要慢得多。

A = sprand(100000,100000,0.01)
w = rand(100000)

@time for i=1:100000
  w += A[:,i]
end
26.304380 seconds (1.30 M allocations: 150.556 GB, 8.16% gc time)

@time for i=1:100000
  A[:,i]'*w
end
0.815443 seconds (921.91 k allocations: 1.540 GB, 5.58% gc time)

我创建了一个我自己的简单稀疏矩阵类型,加法代码与内积相同。

我做错了吗?我觉得应该有一个特殊的功能来做操作w + = A [:,i],但我找不到它。

感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

我在GitHub上问了同样的问题,我们得出以下结论。从Julia 0.4开始添加SparseVector类型,并使用BLAS函数LinAlg.axpy !,它通过稀疏向量x乘以标量来原地更新(可能是密集的)向量y { {1}},即有效地执行a。但是,在Julia 0.4中,它没有正确实施。它仅适用于Julia 0.5

x += a*y

但是,此代码仍然是次优的,因为它创建了SparseVector A [:,i]。可以通过以下功能获得更快的版本:

@time for i=1:100000
  LinAlg.axpy!(1,A[:,i],w)
end
1.041587 seconds (799.49 k allocations: 1.530 GB, 8.01% gc time)

这正是我需要实现的目标,经过一些研究,我们设法到达那里,谢谢大家!

答案 1 :(得分:0)

假设您想要计算w += c * A[:, i],可以通过简单的方法对其进行矢量化:

>>> A = sprand(100000, 100000, 0.01)
>>> c = rand(100000)

>>> r1 = zeros(100000)
>>> @time for i = 1:100000
>>>    r1 += A[:, i] * c[i]
>>> end
29.997412 seconds (1.90 M allocations: 152.077 GB, 12.73% gc time)

>>> @time r2 = sum(A .* c', 2);
1.191850 seconds (50 allocations: 1.493 GB, 0.14% gc time)

>>> all(r1 == r2)
true

首先,创建常量的向量c以与之相乘。然后使用Ac的值按元素A .* c'进行多重播放列,它会在内部进行广播。最后,减少A(部分sum(.., 2))的列。