# Best way to construct a sparse matrix

**URL:** <https://discourse.julialang.org/t/best-way-to-construct-a-sparse-matrix/7657>\
**Category:** Performance\
**Created:** [December 9, 2017, 6:03pm UTC](https://discourse.julialang.org/t/best-way-to-construct-a-sparse-matrix/7657 "2017-12-09T18:03:26Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lbittarello](https://avatars.discourse-cdn.com/v4/letter/l/ed655f/32.png) [@lbittarello](https://discourse.julialang.org/u/lbittarello)\
**Post date:** [December 9, 2017, 6:03pm UTC](https://discourse.julialang.org/t/best-way-to-construct-a-sparse-matrix/7657/1 "2017-12-09T18:03:26Z")

</div>

Hi!

I’m writing a function that constructs a symmetric sparse matrix. I’ve tried two implementations:

```julia
function version1(x::Vector{Date}, k::Function)

    n = length(x)
    mat = speye(Float64, n, n)

    for i = 1:n
        for j = 1:(i - 1)
            w = Dates.value(x[i] - x[j])
            w = k(w)
            (w > 0.0) && (mat[j, i] = w)
        end
    end

    return Symmetric(mat)
end

function version2(x::Vector{Date}, k::Function)

    n = length(x)
    idx₁ = Vector{Int}(1:n)
    idx₂ = Vector{Int}(1:n)
    val = fill(1.0, n)

    for i = 1:n
        for j = 1:(i - 1)
            w = Dates.value(x[i] - x[j])
            w = k(w)
            if w > 0.0
                push!(idx₁, j)
                push!(idx₂, i)
                push!(val, w)
            end
        end
    end

    return Symmetric(sparse(idx₁, idx₂, val))
end

```

I’ve tried them on both on a vector of 5400 dates. After an initial run for compilation, `@time` gives: version1: 7.849785 seconds (48 allocations: 83.900 MiB); version2: 0.676957 seconds (75 allocations: 283.136 MiB, 24.15% gc time). These results are consistent across multiple runs.

Is there are a reason to prefer `version1`? Are the memory savings worth the extra running time?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 9, 2017, 6:17pm UTC](https://discourse.julialang.org/t/best-way-to-construct-a-sparse-matrix/7657/2 "2017-12-09T18:17:38Z")

</div>

Use what is faster. GC will take care of memory.

That said, I would try something like `k.(x .- x')` (adjusted appropriately, but you did not provide an MWE) and then convert it to sparse, if it is sparse. But from the allocations, I am not so sure about that.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 9, 2017, 6:20pm UTC](https://discourse.julialang.org/t/best-way-to-construct-a-sparse-matrix/7657/3 "2017-12-09T18:20:03Z")

</div>

Changing the sparsity pattern is expensive so the second version is likely to prefer.

---

<div class="post-metadata">

**Author:** ![lbittarello](https://avatars.discourse-cdn.com/v4/letter/l/ed655f/32.png) [@lbittarello](https://discourse.julialang.org/u/lbittarello)\
**Post date:** [December 9, 2017, 7:29pm UTC](https://discourse.julialang.org/t/best-way-to-construct-a-sparse-matrix/7657/4 "2017-12-09T19:29:04Z")

</div>

Thanks!

> `k.(x .- x')`

It’s a nice idea. It is faster than `version2` is the input vector is small, but it is slower when it’s large. (My guess: it doesn’t exploit symmetry and `k` is typically expensive to compute.)

> if it is sparse

About 2/3 of the entries are zeros. I don’t know if it qualifies.
