-
-
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
Limit broadcast mechanism over Nullables #19787
Conversation
I'm ok with this limitation to scalars, as was @johnmyleswhite in the other issue, at least for now. My understanding is that the lifting would apply to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs modification of NEWS.md and the manual, in the section on Nullables.
My hero! Thank you. |
@@ -360,16 +343,10 @@ the following rules: | |||
(and treats any `Ref` as a 0-dimensional array of its contents and any tuple | |||
as a 1-dimensional array) expanding singleton dimensions. | |||
|
|||
The following additional rules apply to `Nullable` arguments: | |||
The following additional rule apply to `Nullable` arguments: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rule applies
This seems to simplify things so 👍. One thing that would be great to include in future design considerations for the broadcasting code would be extensibility beyond base. I.e. how user defined arrays should overload broadcast methods. I've been working on such a case in JuliaParallel/DistributedArrays.jl#120 and although it wasn't too hard with the current structure, it didn't feel like extensibility beyond base had been a priority. |
0c7bd1a
to
ce7ebeb
Compare
# broadcast should only "peel" one container level | ||
let io = IOBuffer() | ||
broadcast(x -> print(io, x), [Nullable(1.0)]) | ||
String(take!(io)) == "Nullable{Float64}(1.0)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing @test
_broadcast_type{S}(::Type{S}, f, T::Type, As...) = Base._return_type(f, typestuple(S, T, As...)) | ||
_broadcast_type{T}(::Type{T}, f, A, Bs...) = Base._default_eltype(Base.Generator{ziptype(T, A, Bs...), ftype(f, A, Bs...)}) | ||
_broadcast_type(f, T::Type, As...) = Base._return_type(f, typestuple(T, As...)) | ||
_broadcast_type(f, A, Bs...) = Base._default_eltype(Base.Generator{ziptype(A, Bs...), ftype(f, A, Bs...)}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is used a couple of times in the new sparse code that I suspect you'll have to change done
@@ -73,7 +73,7 @@ function _noshapecheck_map{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecO | |||
fofzeros = f(_zeros_eltypes(A, Bs...)...) | |||
fpreszeros = fofzeros == zero(fofzeros) | |||
maxnnzC = fpreszeros ? min(length(A), _sumnnzs(A, Bs...)) : length(A) | |||
entrytypeC = Base.Broadcast._broadcast_type(Any, f, A, Bs...) | |||
entrytypeC = Base.Broadcast._broadcast_type(f, A, Bs...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(should be squashed on merge to avoid broken intermediate commits)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already squashed it to prevent that.
@@ -360,16 +343,10 @@ the following rules: | |||
(and treats any `Ref` as a 0-dimensional array of its contents and any tuple | |||
as a 1-dimensional array) expanding singleton dimensions. | |||
|
|||
The following additional rules apply to `Nullable` arguments: | |||
The following additional rule applies to `Nullable` arguments: | |||
|
|||
- If there is at least a `Nullable`, and all the arguments are scalars or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the list since there's only one bullet.
# broadcast should only "peel" one container level | ||
let io = IOBuffer() | ||
broadcast(x -> print(io, x), [Nullable(1.0)]) | ||
@test String(take!(io)) == "Nullable{Float64}(1.0)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds a bit weird to use string comparison to test the type of the result. Why not e.g. call push!
to add values to a vector instead?
cb5afa5
to
e5c270a
Compare
I think this is ready, unless there are more comments/concerns. |
Thanks for doing this work. This still needs an update to doc/src/manual/types.md. |
Hoping to review shortly (beginning within the next fifteen minutes). Best! |
@@ -291,22 +282,21 @@ ftype(T::Type, A...) = Type{T} | |||
# if the first argument is Any, then Nullable should be treated like a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete this comment.
@@ -9,6 +9,8 @@ using Base: promote_eltype_op, linearindices, tail, OneTo, to_shape, | |||
import Base: broadcast, broadcast! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the is_nullable_array
import can be removed, and probably the function itself too (in base/nullable.jl
).
@@ -349,8 +332,8 @@ end | |||
|
|||
Broadcasts the arrays, tuples, `Ref`, nullables, and/or scalars `As` to a | |||
container of the appropriate type and dimensions. In this context, anything | |||
that is not a subtype of `AbstractArray`, `Ref` (except for `Ptr`s) or `Tuple`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think Nullable
should be removed from this paragraph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks again!
@@ -349,7 +325,7 @@ end | |||
|
|||
Broadcasts the arrays, tuples, `Ref`, nullables, and/or scalars `As` to a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not from this pull request, but should `Ref`
be plural `Ref`s
for consistency?
@@ -349,7 +325,7 @@ end | |||
|
|||
Broadcasts the arrays, tuples, `Ref`, nullables, and/or scalars `As` to a | |||
container of the appropriate type and dimensions. In this context, anything | |||
that is not a subtype of `AbstractArray`, `Ref` (except for `Ptr`s) or `Tuple`, | |||
that is not a subtype of `AbstractArray`, `Ref` (except for `Ptr`s), `Tuple` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Serial/Oxford) comma after Tuple
?
@@ -359,16 +335,9 @@ the following rules: | |||
(and treats any `Ref` as a 0-dimensional array of its contents and any tuple | |||
as a 1-dimensional array) expanding singleton dimensions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not from this pull request, but perhaps "If there is at least an array or a Ref
in the arguments" -> "If there is at least one array or Ref
in the arguments"? Similarly, perhaps "and treats any Ref
as a 0-dimensional array of its contents and any tuple as a 1-dimensional array" -> "treating Ref
s as 0-dimensional arrays, and tuples as 1-dimensional arrays"?
Edit: Perhaps "If the arguments contain at least one array or Ref
, it returns an array, treating Ref
s as 0-dimensional arrays, tuples as 1-dimensional arrays, and expanding singleton dimensions." would be better still?
- If there is a tuple and a nullable, the result is an error, as this case is | ||
not currently supported. | ||
The following additional rule applies to `Nullable` arguments: If there is at | ||
least a `Nullable`, and all the arguments are scalars or `Nullable`, it returns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps "at least a" should be "at least one"?
@@ -409,3 +409,12 @@ Base.Broadcast.broadcast_c(f, ::Type{Array19745}, A, Bs...) = | |||
@test isa(aa .+ 1, Array19745) | |||
@test isa(aa .* aa', Array19745) | |||
end | |||
|
|||
# broadcast should only "peel off" one container layer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A simpler way to test this behavior might be nice if you can think of one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get.([Nullable(1), Nullable(2)]) == [1, 2]
will work as a simpler test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately I don't have much time for looking for better/simpler tests for today. Maybe we could revisit them another occasion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If @TotalVerb
's suggestion does not suffice, sounds good on this end. Best!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should work fine. Test added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am in no way qualified to provide feedback on the Nullable behavior change's desirability, but this pull request's mechanics LGTM! Thanks @pabloferz
!
as a 1-dimensional array) expanding singleton dimensions. | ||
- If the arguments contain at least one array or `Ref`, it returns an array | ||
(expanding singleton dimensions), and treats `Ref`s as 0-dimensional arrays, | ||
and tuples as a 1-dimensional arrays. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tuples as 1-dimensional arrays
(can ci skip this if you do make check-whitespace locally)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dimensional, not element, sorry - just drop the a now that arrays is plural
@nanosoldier |
Your benchmark job has completed - no performance regressions were detected. A full report can be found here. cc @jrevels |
Looks like that i686 assertion failure "Cannot define a symbol twice!" in the reflection test is repeatable and has been happening since I merged this. Similar to #19792? I'll propose dropping back to LLVM 3.7 for now as a band-aid. |
I don't get why nanosoldier here said "no regressions" but when run on the merged version against its immediate parent commit there were some big regressions - https://github.com/JuliaCI/BaseBenchmarkReports/blob/a1fd436b6823d8e27c7bc1cf3be1b8c1f212bde7/f147aaa_vs_b2ae5a5/report.md I guess the intervening couple of commits that were merged to master between the time the PR run started and this was merged interacted badly here? |
That's strange, the code in this PR does not touch any code related to those regressions. |
I too don't see how a change to broadcasting can possibly affect comprehensions. |
This should address @JeffBezanson's concerns over #16961. That is broadcasting over
Nullable
s treats them as containers only when mixed with scalars. If people need to work with arrays they can use comprehensions, e.g.If someone is relying heavily on arrays of
Nullable
s they probably should be usingNullableArrays
instead.CC. @TotalVerb