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

use afoldl instead of tail recursion for tuples #53665

Merged
merged 1 commit into from
Mar 12, 2024
Merged

use afoldl instead of tail recursion for tuples #53665

merged 1 commit into from
Mar 12, 2024

Conversation

vtjnash
Copy link
Member

@vtjnash vtjnash commented Mar 8, 2024

It is easy to accidentally call these functions (they are used by vcat, which is syntax) with very long lists of values, causing inference to crash and take a long time. The afoldl function can handle that very well however, while naive recursion did not.

Fixes #53585

@vtjnash vtjnash requested a review from JeffBezanson March 8, 2024 21:02
@vtjnash
Copy link
Member Author

vtjnash commented Mar 8, 2024

@nanosoldier runbenchmarks(!"scalar", vs=":master")

@vtjnash vtjnash added compiler:latency Compiler latency merge me PR is reviewed. Merge when all tests are passing labels Mar 8, 2024
@nanosoldier
Copy link
Collaborator

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

@vtjnash
Copy link
Member Author

vtjnash commented Mar 9, 2024

Looks fairly benign except perhaps for

["find", "findprev", ("Vector{Bool}", "50-50")] 3.37 (5%) ❌ 1.00 (1%)

And maybe also a very little bit harder on inference it turns out. We should perhaps add a special case for 2 elements?

@mikmoore
Copy link
Contributor

mikmoore commented Mar 11, 2024

I do find the reduction order in this PR a bit strange. I'll use promote_type(T, S, U, V...) = (@inline; promote_type(T, promote_type(S, afoldl(promote_type, U, V...)))) as the specific example, but it appears to be consistent across this PR.

It appears that we evaluate promote_type(T, S, U, V, W, X) === promote_type(T, promote_type(S, promote_type(promote_type(promote_type(U, V), W), X))). In other words, the association order is (T, (S, (((U, V), W), X))). The previous implementation was right-to-left associative. The new one is right-to-left on the initial applications, then left-to-right on the tail.

Would it make sense to reorder things to have a consistent (strictly leftward or rightward) associativity? I think we generally assume full associativity of promote-like functions, so this hopefully doesn't matter? But I think of issues like #53505, which would be harder to diagnose or fix with non-obvious association orders.

base/promotion.jl Outdated Show resolved Hide resolved
@vtjnash vtjnash removed the merge me PR is reviewed. Merge when all tests are passing label Mar 11, 2024
@vtjnash
Copy link
Member Author

vtjnash commented Mar 12, 2024

@nanosoldier runbenchmarks("inference" || "find", vs=":master")

It is easy to accidentally call these functions (they are used by vcat,
which is syntax) with very long lists of values, causing inference to
crash and take a long time. The `afoldl` function can handle that very
well however, while naive recursion did not.

Fixes #53585
@nanosoldier
Copy link
Collaborator

Your job failed.

@vtjnash
Copy link
Member Author

vtjnash commented Mar 12, 2024

@nanosoldier runbenchmarks("inference" || "find", vs=":master")

@nanosoldier
Copy link
Collaborator

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

@vtjnash vtjnash added the merge me PR is reviewed. Merge when all tests are passing label Mar 12, 2024
@vtjnash vtjnash merged commit df28bf7 into master Mar 12, 2024
7 of 9 checks passed
@vtjnash vtjnash deleted the jn/53585 branch March 12, 2024 18:30
@IanButterworth IanButterworth removed the merge me PR is reviewed. Merge when all tests are passing label Apr 5, 2024
@KristofferC KristofferC added the backport 1.11 Change should be backported to release-1.11 label Apr 18, 2024
KristofferC pushed a commit that referenced this pull request Apr 18, 2024
It is easy to accidentally call these functions (they are used by vcat,
which is syntax) with very long lists of values, causing inference to
crash and take a long time. The `afoldl` function can handle that very
well however, while naive recursion did not.

Fixes #53585

(cherry picked from commit df28bf7)
@KristofferC KristofferC mentioned this pull request Apr 25, 2024
59 tasks
KristofferC added a commit that referenced this pull request May 28, 2024
Backported PRs:
- [x] #53665 <!-- use afoldl instead of tail recursion for tuples -->
- [x] #53976 <!-- LinearAlgebra: LazyString in interpolated error
messages -->
- [x] #54005 <!-- make `view(::Memory, ::Colon)` produce a Vector -->
- [x] #54010 <!-- Overload `Base.literal_pow` for `AbstractQ` -->
- [x] #54069 <!-- Allow PrecompileTools to see MI's inferred by foreign
abstract interpreters -->
- [x] #53750 <!-- inference correctness: fields and globals can revert
to undef -->
- [x] #53984 <!-- Profile: fix heap snapshot is valid char check -->
- [x] #54102 <!-- Explicitly compute stride in unaliascopy for SubArray
-->
- [x] #54070 <!-- Fix integer overflow in `skip(s::IOBuffer,
typemax(Int64))` -->
- [x] #54013 <!-- Support case-changes to Annotated{String,Char}s -->
- [x] #53941 <!-- Fix writing of AnnotatedChars to AnnotatedIOBuffer -->
- [x] #54137 <!-- Fix typo in docs for `partialsortperm` -->
- [x] #54129 <!-- use correct size when creating output data from an
IOBuffer -->
- [x] #54153 <!-- Fixup IdSet docstring -->
- [x] #54143 <!-- Fix `make install` from tarballs -->
- [x] #54151 <!-- LinearAlgebra: Correct zero element in
`_generic_matvecmul!` for block adj/trans -->
- [x] #54213 <!-- Add `public` statement to `Base.GC` -->
- [x] #54222 <!-- Utilize correct tbaa when emitting stores of unions.
-->
- [x] #54233 <!-- set MAX_OS_WRITE on unix -->
- [x] #54255 <!-- fix `_checked_mul_dims` in the presence of 0s and
overflow. -->
- [x] #54259 <!-- Fix typo in `readuntil` -->
- [x] #54251 <!-- fix typo in gc_mark_memory8 when chunking a large
array -->
- [x] #54276 <!-- Fix solve for complex `Hermitian` with non-vanishing
imaginary part on diagonal -->
- [x] #54248 <!-- ensure package callbacks are invoked when no valid
precompile file exists for an "auto loaded" stdlib -->
- [x] #54308 <!-- Implement eval-able AnnotatedString 2-arg show -->
- [x] #54302 <!-- Specialised substring equality for annotated strs -->
- [x] #54243 <!-- prevent `package_callbacks` to run multiple time for a
single package -->
- [x] #54350 <!-- add a precompile signature to Artifacts code that is
used by JLLs -->
- [x] #54331 <!-- correctly track freed bytes in
jl_genericmemory_to_string -->
- [x] #53509 <!-- revert moving "creating packages" from Pkg.jl -->
- [x] #54335 <!-- When accessing the data pointer for an array, first
decay it to a Derived Pointer -->
- [x] #54239 <!-- Make sure `fieldcount` constant-folds for `Tuple{...}`
-->
- [x] #54288
- [x] #54067
- [x] #53715 <!-- Add read/write specialisation for IOContext{AnnIO} -->
- [x] #54289 <!-- Rework annotation ordering/optimisations -->
- [x] #53815 <!-- create phantom task for GC threads -->
- [x] #54130 <!-- inference: handle `LimitedAccuracy` in
`handle_global_assignment!` -->
- [x] #54428 <!-- Move ConsoleLogging.jl into Base -->
- [x] #54332 <!-- Revert "add unsetindex support to more copyto methods
(#51760)" -->
- [x] #53826 <!-- Make all command-line options documented in all
related files -->
- [x] #54465 <!-- typeintersect: conservative typevar subtitution during
`finish_unionall` -->
- [x] #54514 <!-- typeintersect: followup cleanup for the nothrow path
of type instantiation -->
- [x] #54499 <!-- make `@doc x` work without REPL loaded -->
- [x] #54210 <!-- attach finalizer in `mmap` to the correct object -->
- [x] #54359 <!-- Pkg REPL: cache `pkg_mode` lookup -->

Non-merged PRs with backport label:
- [ ] #54471 <!-- Actually setup jit targets when compiling
packageimages instead of targeting only one -->
- [ ] #54457 <!-- Make `String(::Memory)` copy -->
- [ ] #54323 <!-- inference: fix too conservative effects for recursive
cycles -->
- [ ] #54322 <!-- effects: add new `@consistent_overlay` macro -->
- [ ] #54191 <!-- make `AbstractPipe` public -->
- [ ] #53957 <!-- tweak how filtering is done for what packages should
be precompiled -->
- [ ] #53882 <!-- Warn about cycles in extension precompilation -->
- [ ] #53707 <!-- Make ScopedValue public -->
- [ ] #53452 <!-- RFC: allow Tuple{Union{}}, returning Union{} -->
- [ ] #53402 <!-- Add `jl_getaffinity` and `jl_setaffinity` -->
- [ ] #53286 <!-- Raise an error when using `include_dependency` with
non-existent file or directory -->
- [ ] #52694 <!-- Reinstate similar for AbstractQ for backward
compatibility -->
- [ ] #51479 <!-- prevent code loading from lookin in the versioned
environment when building Julia -->
@KristofferC KristofferC removed the backport 1.11 Change should be backported to release-1.11 label May 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:latency Compiler latency
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New stack overflow in type inference on old package.
6 participants