-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Very Poor Performance of Diagonal + SparseMatrixCSC #31770
Comments
Just converting the |
Is this a case automatically covered by #31563? |
This is actually a really easy fix — we're already attempting to convert the # This is the function broadcast uses to convert structured array types to sparse
julia> @time SparseArrays.HigherOrderFns._sparsifystructured(Diagonal(ones(63001)));
8.233826 seconds (42 allocations: 2.963 MiB)
# This is what it uses to do its work — it's a naive O(N^2) algorithm!
julia> @time SparseMatrixCSC(Diagonal(ones(63001)));
8.216935 seconds (88 allocations: 2.966 MiB)
# But we have this specialization that's not being used!
julia> @time sparse(Diagonal(ones(63001)));
0.043160 seconds (70.57 k allocations: 5.605 MiB) |
For sure. I think expected behavior here should be the same as calling |
I agree with @mbauman's suggestion to make sure the conversion is fast I also thought I should point out to @angeris, to be exhaustive, that julia> v = ones(1000) ;
julia> @btime spdiagm(0 => $v) + spdiagm(0 => $v) ; # fast
79.443 μs (44 allocations: 199.05 KiB)
julia> @btime sparse(Diagonal($v)) + spdiagm(0 => $v) ; # fastest
49.983 μs (26 allocations: 143.19 KiB)
julia> @btime Diagonal($v) + spdiagm(0 => $v) ; # slow
5.556 ms (45 allocations: 191.73 KiB)
julia> @btime Diagonal($v) + Diagonal($v) ; # faster than fastest ;)
1.310 μs (2 allocations: 7.95 KiB) So it depends what one plans to do with the matrix because sometimes it is better not to do the conversion to sparse. For example, julia> v1, v2, v3 = rand(1000), rand(1000), rand(1000) ;
julia> @btime $v1' * Diagonal($v2) * $v3 ;
1.751 μs (3 allocations: 64 bytes)
julia> @btime $v1' * sparse(Diagonal($v2)) * $v3 ;
8.863 μs (6 allocations: 31.88 KiB) |
@briochemc Indeed! This was an MWE which came up because I was generating a SparseMatrixCSC from a large, 2D laplacian-type matrix (rather than a diagonal one, via Thanks for the latter example... it's super interesting: I didn't realize the performance would be 8 times worse with the sparse conversion! |
What do you think about that proposal #31563, which would simplify the the solution considerably in view of the problem
|
julia> v1, v2, v3 = rand(1000), rand(1000), rand(1000) ;
julia> @btime $v1' * Diagonal($v2) * $v3 ;
1.751 μs (3 allocations: 64 bytes) is fast because it has a special method, which, in a single loop goes through SparseMatrixCSC(T::SymTridiagonal) = sparse(T)
SparseMatrixCSC(T::Tridiagonal) = sparse(T)
SparseMatrixCSC(B::Bidiagonal) = sparse(B)
SparseMatrixCSC(D::Diagonal) = sparse(D) The other, equivalent option is to add in _sparsifystructured(D::Diagonal{<:Number}) = sparse(D) which would restrict its effect on broadcasting aspects. The equivalence stems from the fact that we have _sparsifystructured(M::AbstractMatrix) = SparseMatrixCSC(M) and since the structured matrices are not Edit: As an alternative, we could move the current, specific code from |
I would fully support moving the relevant |
There appears to be quite poor performance when adding a
Diagonal
matrix to a matrix of typeSparseMatrixCSC
. MWE:gives
@briochemc also reports the same (see #linear-algebra in the julialang Slack)
The text was updated successfully, but these errors were encountered: