# SparseMatrix is very slow

**URL:** https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809
**Category:** General Usage
**Tags:** question
**Created:** [March 31, 2020, 6:03pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809 "2020-03-31T18:03:49Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Tong\_Zhou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tong_zhou/32/13758_2.png) [@Tong\_Zhou](https://discourse.julialang.org/u/Tong_Zhou)
#### Post date: [March 31, 2020, 6:03pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/1 "2020-03-31T18:03:49Z")

</div>

Hi I have the following simple code:

```julia
import SparseArrays

function func0(K::Array{Float64,2}, M::Array{Float64,2}, r::Array{Float64,2}, x::Array{Float64,2}, row::Array{Int32,1}, col::Array{Int32,1}, data::Array{Float64,1}, m::Int64, n::Int64)
    c = SparseArrays.sparse(row, col, data, m, n)
    u = 1.0 ./ x # dense
    ku = (1.0 ./ (transpose(K) * u)) # dense
    v = c .* ku # sparse * dense element-wise product (c is sparse and ku is dense), very very slow
end

```

Somehow line `v = c .* ku` is super slow, 10x slower than when `c` is represented as dense. And `c` is very sparse. Am I missing anything? Thanks!

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [March 31, 2020, 6:26pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/2 "2020-03-31T18:26:24Z")

</div>

My guess is that the broadcast machinery here doesn’t know that the element-wise product of sparse and dense is sparse, so is looping over everything (not the nonzeroes) of the sparse matrix. I think your best bet will be re-writing this as a loop over non-zero elements of c.

---

<div class="post-metadata">

### Author: ![Tong\_Zhou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tong_zhou/32/13758_2.png) [@Tong\_Zhou](https://discourse.julialang.org/u/Tong_Zhou)
#### Post date: [March 31, 2020, 6:33pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/3 "2020-03-31T18:33:34Z")

</div>

I see. Thanks a lot for the suggestion! But the slowdown seems beyond the overhead of looping all elements in the sparse matrix. I tried to conver sparse matrix `c` to dense, and then do the element-wise product, and that was much faster although it also loops over all elements.

Is it possible that the sparse matrix is CSC format and the dense array is in row-major order, so the iteration is causing a lot of cache misses?

Thanks!

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [March 31, 2020, 6:35pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/4 "2020-03-31T18:35:39Z")

</div>

Iterating over sparse arrays is much more expensive than iterating over dense arrays.  
Dense arrays in Julia are also column major.

---

<div class="post-metadata">

### Author: ![Tong\_Zhou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tong_zhou/32/13758_2.png) [@Tong\_Zhou](https://discourse.julialang.org/u/Tong_Zhou)
#### Post date: [March 31, 2020, 7:12pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/5 "2020-03-31T19:12:53Z")

</div>

Oh oh I see. Thanks!

---

<div class="post-metadata">

### Author: ![mlanghinrichs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mlanghinrichs/32/50371_2.png) [@mlanghinrichs](https://discourse.julialang.org/u/mlanghinrichs)
#### Post date: [March 31, 2020, 7:16pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/6 "2020-03-31T19:16:35Z")

</div>

A good iteration scheme when using sparse matrices is the following (from the documentation: [Sparse Arrays · The Julia Language](https://docs.julialang.org/en/v1/stdlib/SparseArrays/))

```julia
A = sparse(I,J,V)
rows = rowvals(A)
vals = nonzeros(A)
m, n = size(A)
for j = 1:n
   for i in nzrange(A, j)
      row = rows[i]
      val = vals[i]
      # perform sparse wizardry...
   end
end

```

You could probably adapt it to do your multiplication.

And welcome to the Julia community! 🙂

---

<div class="post-metadata">

### Author: ![Tong\_Zhou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tong_zhou/32/13758_2.png) [@Tong\_Zhou](https://discourse.julialang.org/u/Tong_Zhou)
#### Post date: [March 31, 2020, 8:52pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/7 "2020-03-31T20:52:25Z")

</div>

Thanks a lot! That example is very helpful!!

Btw, are such methods on SparseMatrix documented somewhere? like rowvals(A) and nonzeros(A)?

I tried to do `methodswith(SparseMatrixCSC)`, but it doesn’t have any comments for a method.

Thanks!

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [March 31, 2020, 8:57pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/8 "2020-03-31T20:57:13Z")

</div>

I would start reading here [Sparse Arrays · The Julia Language](https://docs.julialang.org/en/v1/stdlib/SparseArrays/index.html) if I were you.

---

<div class="post-metadata">

### Author: ![mlanghinrichs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mlanghinrichs/32/50371_2.png) [@mlanghinrichs](https://discourse.julialang.org/u/mlanghinrichs)
#### Post date: [March 31, 2020, 8:57pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/9 "2020-03-31T20:57:49Z")

</div>

yes sure, just scroll down in the link I sent you. For example, rowvals would be [here](https://docs.julialang.org/en/v1/stdlib/SparseArrays/#SparseArrays.rowvals).

What you can also do: In the Julia REPL enter “?” to get in the help mode. Then you can also enter e.g. “rowvals” to get documentation info:

```julia
julia> ?
help?> rowvals
search: rowvals

  rowvals(A::SparseMatrixCSC)

  Return a vector of the row indices of A. Any modifications to the returned vector will mutate A as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural nonzero values. See also nonzeros and nzrange.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> A = sparse(2I, 3, 3)
  3×3 SparseMatrixCSC{Int64,Int64} with 3 stored entries:
    [1, 1] = 2
    [2, 2] = 2
    [3, 3] = 2
  
  julia> rowvals(A)
  3-element Array{Int64,1}:
   1
   2
   3

```

---

<div class="post-metadata">

### Author: ![Tong\_Zhou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tong_zhou/32/13758_2.png) [@Tong\_Zhou](https://discourse.julialang.org/u/Tong_Zhou)
#### Post date: [March 31, 2020, 9:00pm UTC](https://discourse.julialang.org/t/sparsematrix-is-very-slow/36809/10 "2020-03-31T21:00:16Z")

</div>

I see. Thanks a lot for the detailed example! Appreciate it!
