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

RFC: Continuation of #20607, revision of sum, prod, and reduce #22825

Closed
wants to merge 5 commits into from

Conversation

TotalVerb
Copy link
Contributor

@TotalVerb TotalVerb commented Jul 15, 2017

(Continuation of #20607 by @felixrehren. The intermediate commit should be preserved, but we should run the tests on it.)

This is not done yet. I'm creating this PR to solicit feedback about this approach.

Remaining things to do:

  • mr_empty should grow a specialization for compositions of promote_sys_size and something else (avoids regressions in empty case of sum(abs, ...)). This empty summation is apparently untested so tests will be needed to.
  • Review remaining methods of sum and prod to ensure things are consistent (and test)
  • Review and test that the dimensional reduction methods work properly
  • Document properly the new behavior
  • Doctests
  • Run test suite on the intermediate commit
  • Nanosoldier and make sure no perf regressions
  • NEWS entry

Certain design decisions that are in addition to the consensus discussed in #20560, #20607, and #21523, (I'm fairly convinced that they're the right thing to do, but please leave feedback if you disagree):

  • sum(Int8(1)) is now Int(1) instead of Int8(1). The previous behavior was inconsistent with other iterators. While it's true that this case cannot cause any problems, it's preferable in my opinion to always return a consistent result.
  • r_promote and related things are entirely gone. It's too much effort to properly deprecate them. It's not particularly useful anyway: promotion behavior can be passed in by the caller through v0 or f.
  • sum of integer ranges has always had this behavior by accident... by calling length() and using the result of that in the calculation. So I've left them alone.
  • I restricted the mr_empty fallback for & to apply only to the identity / Bool case.
  • Some miscellaneous overhaul of how mr_empty is defined to look more sane.

Certain things NOT addressed in this PR:

  • sum, prod of Tuples ignores the promotion behavior of arrays and other iterables. TODO items have been added.

@bramtayl
Copy link
Contributor

bramtayl commented Jul 16, 2017

mr_empty 'cause you can look right through me
Walk right by me and never know I'm there

@stevengj
Copy link
Member

stevengj commented Jul 16, 2017

sum(Int8(1)) is now Int(1) instead of Int8(1).

I don't see any need for this. Nor is it inconsistent, in the sense of type-stability. Simpler to just keep sum(x::Number) = x?

base/reduce.jl Outdated
mr_empty(::typeof(identity), op::typeof(+), T) = zero(T)::T
mr_empty(::typeof(abs), op::typeof(+), T) = abs(zero(T)::T)
mr_empty(::typeof(abs2), op::typeof(+), T) = abs2(zero(T)::T)
mr_empty(::typeof(identity), op::typeof(*), T) = one(T)::T
Copy link
Member

Choose a reason for hiding this comment

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

This is incorrect, since one(T) may not be of type T for a dimensionful type. Just get rid of the typeassert here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will fix, thanks. Actually it would be nice to see if any of these type annotations are really still necessary, since MethodError now infers as Union{} instead of Any. I will remove them all and we can see if any benchmarks regress.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All these annotations are gone now.

@@ -574,14 +577,22 @@ any!(r, A)
for (fname, op) in [(:sum, :+), (:prod, :*),
(:maximum, :scalarmax), (:minimum, :scalarmin),
(:all, :&), (:any, :|)]
function compose_pss(x)
Copy link
Contributor

Choose a reason for hiding this comment

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

only used once, abbreviating the name isn't that helpful

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense, wrote it in full

@stevengj
Copy link
Member

@TotalVerb, I agree it's probably not worth a special case for sum(::Number).

@StefanKarpinski
Copy link
Sponsor Member

This got stalled out, but it would be great to make some progress here. Anything we can do to help?

@TotalVerb
Copy link
Contributor Author

Going to pick this back up now and work through the remaining TODO items. Mostly, it should be just testing and confirming the consistency of the slice-based reductions.

@TotalVerb
Copy link
Contributor Author

Another change to add to the unrelated changes list: I restricted the mr_empty fallback for & to apply only to the identity / Bool case.

@TotalVerb
Copy link
Contributor Author

The code change is done. I still need to write up a NEWS entry and some doctests. In the meantime, could someone run nanosoldier on the latest revision?

cc @StefanKarpinski

@TotalVerb TotalVerb changed the title WIP: Continuation of #20607, revision of sum, prod, and reduce RFC: Continuation of #20607, revision of sum, prod, and reduce Sep 4, 2017
@@ -228,38 +228,41 @@ pairwise_blocksize(::typeof(abs2), ::typeof(+)) = 4096

# handling empty arrays
_empty_reduce_error() = throw(ArgumentError("reducing over an empty collection is not allowed"))
mr_empty(f, op, T) = _empty_reduce_error()
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

RIP Mr. Empty :(

@StefanKarpinski
Copy link
Sponsor Member

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Something went wrong when running your job:

NanosoldierError: failed to run benchmarks against primary commit: failed process: Process(`sudo cset shield -e su nanosoldier -- -c ./benchscript.sh`, ProcessExited(1)) [1]

Logs and partial data can be found here
cc @ararslan

@TotalVerb
Copy link
Contributor Author

If this is the error, it looks unrelated:

ERROR: LoadError: MethodError: no method matching ind2sub(::Tuple{Int64,Int64}, ::CartesianIndex{2})
Closest candidates are:
  ind2sub(!Matched::AbstractArray, ::Any) at abstractarray.jl:1617
  ind2sub(::Tuple{Vararg{Integer,N}} where N, !Matched::Integer) at abstractarray.jl:1694
ind2sub(::Union{Tuple{Vararg{Integer,N}}, Tuple{Vararg{AbstractUnitRange,N}}}, !Matched::AbstractArray{#s51,1} where #s51<:Integer) where N at abstractarray.jl:1750

Please excuse me if this is unrelated, as I have not read nanosoldier logs before.

@ararslan
Copy link
Member

ararslan commented Sep 6, 2017

Unrelated to this PR. Looks like BaseBenchmarks was broken by #22907.

@TotalVerb
Copy link
Contributor Author

Could someone please run nanosoldier again?

@KristofferC
Copy link
Sponsor Member

@nanosoldier runbenchmarks(ALL, vs=":master")

1 similar comment
@ararslan
Copy link
Member

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Something went wrong when running your job:

NanosoldierError: failed to run benchmarks against primary commit: failed process: Process(`sudo cset shield -e su nanosoldier -- -c ./benchscript.sh`, ProcessExited(1)) [1]

Logs and partial data can be found here
cc @ararslan

@nanosoldier
Copy link
Collaborator

Something went wrong when running your job:

NanosoldierError: failed to run benchmarks against primary commit: failed process: Process(`sudo cset shield -e su nanosoldier -- -c ./benchscript.sh`, ProcessExited(1)) [1]

Logs and partial data can be found here
cc @ararslan

@TotalVerb
Copy link
Contributor Author

This failure looks related to the mapreduce changes. I'll investigate.

TotalVerb added a commit to TotalVerb/BaseBenchmarks.jl that referenced this pull request Sep 10, 2017
JuliaLang/julia#22825 will change the behavior of `mapreduce` to never promote, so to retain the previous behavior it must be changed to `sum`.
@TotalVerb
Copy link
Contributor Author

Could someone please review and merge the associated BaseBenchmarks PR,
JuliaCI/BaseBenchmarks.jl#115

ararslan pushed a commit to JuliaCI/BaseBenchmarks.jl that referenced this pull request Sep 12, 2017
JuliaLang/julia#22825 will change the behavior of `mapreduce` to never promote, so to retain the previous behavior it must be changed to `sum`.
@ararslan
Copy link
Member

I'm retuning the Nanosoldier benchmarks now that your change has been merged and I'll start a new Nanosoldier run here once that's done.

base/reduce.jl Outdated
# reduced over to an appropriate size.
promote_sys_size(x) = x
promote_sys_size(x::SmallSigned) = Int(x)
promote_sys_size(x::SmallUnsigned) = UInt(x)
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

This should also include Bool. I believe that will fix the problem in BaseBenchmarks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I'll fix and test this.

@JeffBezanson
Copy link
Sponsor Member

Bump. This is so close!

@TotalVerb
Copy link
Contributor Author

Ok, here's a revised approach that I hope should handle Bool well. It passes test-reduce locally, so could someone try running nanosoldier again?

@ararslan
Copy link
Member

ararslan commented Oct 6, 2017

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@JeffBezanson
Copy link
Sponsor Member

Once this passes I'll squash all but the first commit and merge this.

@JeffBezanson
Copy link
Sponsor Member

Squashed version is on master; github might not pick up that this has been merged.

@TotalVerb TotalVerb deleted the fw/wider branch October 15, 2017 19:03
@TotalVerb
Copy link
Contributor Author

Thanks!

@StefanKarpinski
Copy link
Sponsor Member

Thanks so much @TotalVerb for persisting with this change!

tkoolen added a commit to tkoolen/TypeSortedCollections.jl that referenced this pull request Dec 4, 2017
tkoolen added a commit to tkoolen/TypeSortedCollections.jl that referenced this pull request Dec 4, 2017
Use Compat.Test instead of Base.Test, adapt to JuliaLang/julia#22825
simonbyrne added a commit that referenced this pull request Dec 12, 2017
Since the demise of `r_promote` in #22825, there is now a type-instability in `mapreduce` if the operator does not give an element of the same type as the input. This arose during my implementation of Kahan summation using a reduction operator, see: JuliaMath/KahanSummation.jl#7

This adds a `mapreduce_single` function which defines what the result should be in these cases.
simonbyrne added a commit that referenced this pull request Dec 14, 2017
Since the demise of `r_promote` in #22825, there is now a type-instability in `mapreduce` if the operator does not give an element of the same type as the input. This arose during my implementation of Kahan summation using a reduction operator, see: JuliaMath/KahanSummation.jl#7

This adds a `mapreduce_single` function which defines what the result should be in these cases.
simonbyrne added a commit that referenced this pull request Jan 3, 2018
Since the demise of `r_promote` in #22825, there is now a type-instability in `mapreduce` if the operator does not give an element of the same type as the input. This arose during my implementation of Kahan summation using a reduction operator, see: JuliaMath/KahanSummation.jl#7

This adds a `mapreduce_single` function which defines what the result should be in these cases.
JeffBezanson pushed a commit that referenced this pull request Jan 4, 2018
Since the demise of `r_promote` in #22825, there is now a type-instability in `mapreduce` if the operator does not give an element of the same type as the input. This arose during my implementation of Kahan summation using a reduction operator, see: JuliaMath/KahanSummation.jl#7

This adds a `mapreduce_single` function which defines what the result should be in these cases.
@NHDaly NHDaly mentioned this pull request Jan 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants