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

Unalias off-diagonals in Tridiagonal constructor #51763

Merged
merged 6 commits into from
Dec 5, 2023

Conversation

jishnub
Copy link
Contributor

@jishnub jishnub commented Oct 18, 2023

As noted by Samuel Isaacson on slack, currently,

julia> e = ones(4); f = e[1:end-1];

julia> T = Tridiagonal(f, 2e, f)
4×4 Tridiagonal{Float64, Vector{Float64}}:
 2.0  1.0        
 1.0  2.0  1.0    
     1.0  2.0  1.0
         1.0  2.0

julia> T ./= 10
4×4 Tridiagonal{Float64, Vector{Float64}}:
 0.2   0.01         
 0.01  0.2   0.01    
      0.01  0.2   0.01
           0.01  0.2

This PR resolves such issues by ensuring that the off-diagonals are not aliased. After this,

julia> T ./= 10
4×4 Tridiagonal{Float64, Vector{Float64}}:
 0.2  0.1        
 0.1  0.2  0.1    
     0.1  0.2  0.1
         0.1  0.2

This also gets the in-place lu! to work on such an array, which otherwise wouldn't as the off-diagonals are aliased.

It was suggested in JuliaLang/LinearAlgebra.jl#706 that a warning for mutable functions may suffice (instead of an explicit check for dl !== du), but preventing the aliasing seems to be a better solution that would avoid various bugs.

@jishnub jishnub added the linear algebra Linear algebra label Oct 18, 2023
@mbauman
Copy link
Member

mbauman commented Oct 18, 2023

I like this much better, but it looks like you'll also need to revert #35197 (as those tests added there should fail).

@mbauman mbauman requested a review from andreasnoack October 18, 2023 17:25
@dkarrasch
Copy link
Member

dkarrasch commented Oct 19, 2023

I believe we have tests in the lu! code (and perhaps elsewhere) that check for potential aliasing. Those could be removed. Moreover, this might help to simplify recent BunchKaufman -eigen-related efforts. @aravindh-krishnamoorthy

EDIT: 🤦 That's exactly what @mbauman was talking about.

@@ -82,7 +82,7 @@ end
@test TT == Matrix(TT)
@test TT.dl === y
@test TT.d === x
@test TT.du === y
@test TT.du == y
Copy link
Member

Choose a reason for hiding this comment

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

Should we document which off-diagonal is aliased to the argument of the constructor and which one may be just a copy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I feel we should document that the off diagonals shouldn't be aliased, and leave the de-aliasing as an implementation detail.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hello, as a Julia beginner and new user, I feel I might prefer to have a warning here along with the unaliasing if I alias dl and du (and not an error as earlier). The reason is that, in Julia, I always expect matrix assignments and calls to reuse the same memory. Silent unaliasing of dl and du would be (from my point of view) unexpected behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added a comment to the docstring explaining that du is copied if aliasing is detected.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you very much, @jishnub. I'm not sure if it makes sense, in my comment above, I was actually referring to a runtime warning that would seem most correct to me as a beginner.

Copy link
Member

Choose a reason for hiding this comment

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

I think runtime warnings may ruin performance. Moreover, we have the hint in the documentation, so it's not exactly "silent".

@dkarrasch
Copy link
Member

Is this ready to go? I'd say so.

@jishnub
Copy link
Contributor Author

jishnub commented Nov 25, 2023

Yeah, seems ok to me

@PallHaraldsson
Copy link
Contributor

This seems better since you prevent a bug, wrong results.

I'm just curious this makes a copy sometimes, e.g. in that case I presume, and why didn't it throw in the old code?

_unaliascopy(A, C) = throw(ArgumentError("""

Sometimes you do not want allocations, and that is now a possibility, but also still the possibility of throwing (for unusual types).

@dkarrasch
Copy link
Member

It didn't throw in the old code because there was no aliasing check included. It's true, it may now imply an allocation that may not be intended by the user, but it appears only once at construction, and afterwards makes no difference except that it avoids errors.

@dkarrasch dkarrasch added the merge me PR is reviewed. Merge when all tests are passing label Dec 5, 2023
@dkarrasch dkarrasch merged commit 7055644 into master Dec 5, 2023
6 checks passed
@dkarrasch dkarrasch deleted the jishnub/unaliastridiag branch December 5, 2023 12:59
@dkarrasch dkarrasch removed the merge me PR is reviewed. Merge when all tests are passing label Dec 5, 2023
aravindh-krishnamoorthy added a commit to aravindh-krishnamoorthy/julia that referenced this pull request Dec 5, 2023
…ti-aliasing implementation in JuliaLang#51763 + include comments in symmetriceigen.jl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
linear algebra Linear algebra
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants