Skip to content

Conversation

@bkamins
Copy link
Member

@bkamins bkamins commented Mar 29, 2023

Currently broadcasting does not detect that slices might alias with parent:

julia> x = rand(2, 2)
2×2 Matrix{Float64}:
 0.63266   0.51432
 0.787383  0.21117

julia> Base.mightalias(x, eachrow(x))
false

See https://discourse.julialang.org/t/unexpected-broadcasting-behavior-involving-eachrow/96781 for an example when this creates a problem.

@N5N3
Copy link
Member

N5N3 commented Mar 29, 2023

We typically never do alias check between value and container though. (That would be quite costy in many cases)

julia> A = [1]; B = [A;]; Base.mightalias(A, B)
false

julia> A = [1]; B = Ref(A); Base.mightalias(A, B)
false

@adienes
Copy link
Member

adienes commented Mar 29, 2023

Not to sound too dramatic / inflammatory, but I feel pretty certain that the behavior OP originally noted in the Discourse is confusing and bad, and if not addressed in some way will become another thing pointed at during claims of "Julia has correctness issues"

The equivalent code in numpy works exactly as expected

import numpy as np
x = np.random.random((6,4))
x /= np.linalg.norm(x, axis=1).reshape(-1, 1)
np.linalg.norm(x, axis=1) # returns [1, 1, ... 1]

but Julia:

using LinearAlgebra: norm
x = rand(6, 4)
x ./= norm.(eachrow(x))
norm.(eachrow(x)) # returns something very surprising!

That's the intuitive/obvious implementation to me and I could see this resulting in an extremely insidious bug.

@bkamins
Copy link
Member Author

bkamins commented Mar 29, 2023

We typically never do alias check between value and container though.

I agree, but in this case I would quality AbstractSlices as a view (for which we do alias check).

@mcabbott
Copy link
Contributor

np.linalg.norm(x, axis=1)

This is equivalent to norm(x; dims=2), which is JuliaLang/LinearAlgebra.jl#697.

Even if aliasing were avoided, x ./= norm.(eachrow(x)) is a bad pattern as it will call norm N^2 times, and won't work with eachcol.

@bkamins
Copy link
Member Author

bkamins commented Mar 31, 2023

We have the same issue with Ref. Do we also want to fix it?

Also - are these changes considered breaking or not? (probably they are breaking, and should be marked for 2.0 release)

@bkamins bkamins changed the title Improve handling of aliasing of AbstractSlices DO NOT MERGE YET: Improve handling of aliasing of AbstractSlices Mar 31, 2023
@bkamins
Copy link
Member Author

bkamins commented Mar 31, 2023

Thank you for approving. I added "DO NOT MERGE YET" to the name (I cannot set labels in this repository) as I think we need a broader discussion if we want this change:

  1. If it should be considered breaking or not
  2. If we also should add handling of other wrappers in a similar way(especially Ref)

If it is decided that we go for the change the PR still needs NEWS.md entry + documentation improvement (I will work on if after the consensus if the change is desirable is reached).

@mbauman
Copy link
Member

mbauman commented Mar 31, 2023

  1. IMO: This is not breaking. It changes behaviors, yes, but I think it goes from a buggier behavior to a more consistent one.

  2. We have an established pattern of unaliasing AbstractArrays and AbstractSlices <: AbstractArray. Going more general and making Ref (and Tuple and other containers) also participate in unaliasing is a good question but I think it's a completely separate decision that should be addressed independently.

@IanButterworth IanButterworth added the DO NOT MERGE Do not merge this PR! label Mar 31, 2023
@bkamins bkamins changed the title DO NOT MERGE YET: Improve handling of aliasing of AbstractSlices Improve handling of aliasing of AbstractSlices Mar 31, 2023
@mcabbott
Copy link
Contributor

Should this be backported to 1.9? No question about breaking if Slices isn't out yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DO NOT MERGE Do not merge this PR!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants