Skip to content
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

SparseArrays: Speed up right-division by diagonal matrices #35533

Merged
merged 2 commits into from
Apr 27, 2020

Conversation

eschnett
Copy link
Contributor

No description provided.

Copy link
Member

@dkarrasch dkarrasch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 2-arg *div!s should work, at least they exist.

stdlib/SparseArrays/src/linalg.jl Outdated Show resolved Hide resolved
stdlib/SparseArrays/src/linalg.jl Outdated Show resolved Hide resolved
@dkarrasch
Copy link
Member

S**t, I thought I wrote a long comment, but must have forgotten to push the button. To make the long story short, the left-division is currently working nicely, there is no need for an additional method. The right-division is not too bad in that it doesn't fall back to generic dense methods or whatever, but can be improved still

using SparseArrays, LinearAlgebra, BenchmarkTools, Test

A = sprand(10000,10000,0.1);
D = Diagonal(rand(10000));

function mydiv(A::AbstractMatrix, D::Diagonal)
    rdiv!(typeof(oneunit(eltype(A))/oneunit(eltype(D))).(A), D)
end

@test A/D  mydiv(A, D)
@btime mydiv($A, $D);
@btime $A / $D;
@btime $D \ $A; # for comparison with mydiv

My function mydiv is meant to be the relaxation of

(/)(A::Union{StridedMatrix, AbstractTriangular}, D::Diagonal) =
rdiv!((typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A), D)

to AbstractMatrixes. I'd suggest to relax that method, remove the newly added methods, and keep the tests, maybe adding further sparsity tests.

@eschnett
Copy link
Contributor Author

@dkarrasch Do you suggest to provide a generic method for AbstractMatrix that handles division by diagonal matrices? It seems dangerous to apply a point-wise operation to them since we know nothing about their internal storage. We can't guarantee that the result of a division by a diagonal matrix can be stored in their internal representation. For example, this function would fail if called for UniformScaling.

Should we instead relax the existing division operator to include sparse matrices only?

@dkarrasch
Copy link
Member

Do you suggest to provide a generic method for AbstractMatrix that handles division by diagonal matrices?

Yes. Look at this one:

(\)(D::Diagonal, A::AbstractMatrix) =
ldiv!(D, (typeof(oneunit(eltype(D))/oneunit(eltype(A)))).(A))

If there is an issue with the underlying ldiv! for that specific array type, we'll get a MethodError, and I think that's just fine. IIRC, UniformScaling is not an AbstractMatrix. And this one is called currently for the left-division of a sparse matrix by a Diagonal.

@eschnett
Copy link
Contributor Author

@dkarrasch Done.

@dkarrasch
Copy link
Member

Ok, my sincere apologies for the mess. Now we've got a method ambiguity. Apparently, there is a subtle reason for the different signatures of ldiv! and rdiv!, for why one can handle AbstractMatrix and the other is more specialized. So I hope we should be fine with adding

function (/)(A::AbstractSparseMatrixCSC, D::Diagonal)
    T = typeof(oneunit(eltype(A))/oneunit(eltype(D)))
    rdiv!(LinearAlgebra.copy_oftype(A, T), D)
end

to SparseArrays (and leaving the one in diagonal.jl unchanged compared to master).

Initially, my main point was that D \ A works just fine, so we don't need to change anything to allow for that. A / D also works, but has a little overhead due to the multiple adjoints, so we can improve that.

Copy link
Member

@dkarrasch dkarrasch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry again for the back and forth, this time just a trivial comment on the tests, and I hope with my last suggestion we'll be all set.

stdlib/SparseArrays/test/sparse.jl Outdated Show resolved Hide resolved
stdlib/SparseArrays/test/sparse.jl Outdated Show resolved Hide resolved
@dkarrasch dkarrasch changed the title SparseArrays: Allow division by diagonal matrices SparseArrays: Speed up right-division by diagonal matrices Apr 23, 2020
@eschnett
Copy link
Contributor Author

@dkarrasch Done. Thanks for the suggestions; this is now a much better implementation.

@dkarrasch
Copy link
Member

@eschnett Ok, the tests look good now, but you still have the method ambiguity due to my own bold suggestion (sorry again). You'll need to undo the change in LinearAlgebra/diagonal.jl, and add #35533 (comment) to SparseArrays/linalg.jl. Then I'd expect this to pass tests.

@eschnett
Copy link
Contributor Author

Sorry, did not see your final comment earlier.

I didn't spot the method ambiguity when I ran the test suite locally.

@dkarrasch dkarrasch merged commit 7d27fa8 into JuliaLang:master Apr 27, 2020
mbauman added a commit that referenced this pull request Apr 28, 2020
* origin/master: (833 commits)
  Improve typesubtract for tuples (#35600)
  Make searchsorted*/findnext/findprev return values of keytype (#32978)
  fix buggy rand(RandomDevice(), Bool) (#35590)
  remove `Ref` allocation on task switch (#35606)
  Revert "partr: fix multiqueue resorting stability" (#35589)
  exclude types with free variables from `type_morespecific` (#35555)
  fix small typo in NEWS.md (#35611)
  enable inline allocation of structs with pointers (#34126)
  SparseArrays: Speed up right-division by diagonal matrices (#35533)
  Allow hashing 1D OffsetArrays
  NEWS item for introspection macros (#35594)
  Special case empty covec-diagonal-vec product (#35557)
  [GCChecker] fix a few tests by looking through casts
  Use norm instead of abs in generic lu factorization (#34575)
  [GCChecker,NFC] run clang-format -style=llvm
  [GCChecker] fix tests and add Makefile
  Add introspection macros support for dot syntax (#35522)
  Specialize `union` for `OneTo` (#35577)
  add pop!(vector, idx, [default]) (#35513)
  bump Pkg version (#35584)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants