SparseMatrix or SArray, MArray?

I’m just getting used to Julia and therefore have very basic questions:

  1. SparseMatrix
    I have a little sparse matrix (only 11 Rows). Since the number of entries for storage as SparseMatrixCSC must be known: Will such a small matrix be stored on the stack or do I have to weigh up whether the SparseMatrix or SArray will bring me greater benefit?

  2. MArray
    There is also MArray in the package StaticArrays. When does one use MArray?

I’m looking forward to your answers :wink:

From those options I would bet on the static array. Or, maybe, define a custom immutable struct with two static vectors for the values and indices.

Concerning the MArray, I cannot say much. Whenever I thought they would be useful the actual immutable arrays resulted to be faster.

1 Like

Well, MArrays are useful when you want to mutate vectors in place, e.g.:

# calculate the drag of one tether segment
function calc_drag(s, v_segment, unit_vector, rho, last_tether_drag, v_app_perp, area)
    s.v_apparent .= s.v_wind_tether - v_segment
    v_app_norm = norm(s.v_apparent)
    v_app_perp .= s.v_apparent .- dot(s.v_apparent, unit_vector) .* unit_vector
    last_tether_drag .= -0.5 * set.cd_tether * rho * norm(v_app_perp) * area .* v_app_perp
    v_app_norm
end 

You cannot easily do that with SArrays.

And MArray and SArray are good for up to about 100 elements. I would not use a sparse matrix if I have less than 100 elements.

1 Like

specifically, you shouldn’t use SparseMatrixCSC with less than around 10000 elements. If your matrix is small enough to fit in L2 cache, it’s probably not worth the 10x overhead to index. Special types of Sparse matrices (like Diagonal Banded etc) on the other hand are worth it at much smaller sizes.

4 Likes

For convenience, yes, but this is what I mean:

using StaticArrays, BenchmarkTools, Setfield

function mut!(A)
  A .= A .+ 1
end
Base.setindex!(m::SMatrix,value,i,j) = @set! m[i,j] = value

A1 = rand(3,3)

A2 = rand(MMatrix{3,3,Float64})

A3 = rand(SMatrix{3,3,Float64})

@btime mut!($A1)

@btime mut!($A2)

@btime mut!($A3)



Results:

  14.548 ns (0 allocations: 0 bytes)
  4.733 ns (0 allocations: 0 bytes)
  1.791 ns (0 allocations: 0 bytes)

This actually makes me wonder how and why MMatrix are actually implemented as they are, and if that could not be improved.

(it has not escaped to me that the function above does not mutate the matrix if it is a static matrix, and one may have to appeal to MMatrix if passing it to another code over which one does not have access to define A = mut!(A)) .

Thanks for your help.
I’m afraid I’ve left out an important piece of information:
I have an 11 * 11 matrix with entries only on 3 diagonals. It’s a SparseMatrixCSC but I created it with spdiagm, that’s what I should have said about it. The overhead should therefore be significantly lower.
It’s kind of a diffusion matrix that never gets changed and I was wondering if I couldn’t take advantage of this fact by making it somehow immutable.

You have a tiny matrix with a low sparsity (30% nonzero). A dense matrix will be faster than a sparse CSC matrix here.

1 Like

Okay, then a SArray is probably the right choice.
Thank you for your prompt reply