-
-
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
Improve evaluation of nested ComposedFunction
s
#45925
Conversation
You can test this improvement as like:
include("compiler/irutils.jl")
const issue_45877 = reduce(∘, fill(sin,500))
@test fully_eliminated() do
issue_45877(1.0)
end |
6582429
to
07ffbaf
Compare
@aviatesk can you explain why the julia> const g = reduce(∘, fill(sin,500));
julia> only(code_typed() do
Base.unwrap_composed(g)
end)[2]
NTuple{500, typeof(sin)}
julia> Base.infer_effects() do
Base.unwrap_composed(g)
end
(+c,+e,+n,!t,+s) So inference succeeds which implies that it follows the recursion to the end, therefore obviously has figured out that there is an end. But the effects don't seem to catch that. Is there some way we could make the effects here more precise? If we could avoid the |
While debugging #45781, I found that the root problem there was that I think we are tainting the effect too aggressively here: julia/base/compiler/abstractinterpretation.jl Lines 619 to 622 in b11ccae
since edgecycle basically means there are calls of same Method , but still their MethodInstance s can be different.We can sync them more if we taint the terminates effect by detecting recursion per MethodInstance basis. So basically we need to implement such analysis (maybe reusing a part of the similar type-level analysis for interprocedural recursion detection).
|
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.
We can try to improve the recursion detection for effect analysis instead, but I'm also fine with merging this for now and tackle the improvement later.
I don't mind either way. I won't have the bandwidth to look at improving effect analysis anytime soon, don't know whether you can tackle it in the foreseeable future. If no, we probably should merge as is. But I have no personal interest in deeply nested composed functions, so no hurry from my side. |
LGTM. I think the |
07ffbaf
to
7006603
Compare
* Add (the equivalent of) `@assume_effects :terminates_globally` to `unwrap_composed`. Although it could be inferred as `Const`, without the annotation, it was not elided for too complex inputs, resulting in unnecessary runtime overhead. * Reverse recursion order in `call_composed`. This prevents potentially changing argument types being piped through the recursion, making inference bail out. With the reversed order, only the tuple of remaining functions is changing during recursion and is becoming strictly simpler, letting inference succeed.
Motivation is to be able to use `@assume_effects` by including that file at an appropriate position during bootstrap.
This reverts commit bb5ea07319a47d325b57b7b62c561bd6fa325838.
7006603
to
5b7ec82
Compare
* ~~Add (the equivalent of) `@assume_effects :terminates_globally` to `unwrap_composed`. Although it could be inferred as `Const`, without the annotation, it was not elided for too complex inputs, resulting in unnecessary runtime overhead.~~ EDIT: now JuliaLang#45993 is merged and this part isn't included. * Reverse recursion order in `call_composed`. This prevents potentially changing argument types being piped through the recursion, making inference bail out. With the reversed order, only the tuple of remaining functions is changing during recursion and is becoming strictly simpler, letting inference succeed. Co-authored-by: Shuhei Kadowaki <aviatesk@gmail.com>
* ~~Add (the equivalent of) `@assume_effects :terminates_globally` to `unwrap_composed`. Although it could be inferred as `Const`, without the annotation, it was not elided for too complex inputs, resulting in unnecessary runtime overhead.~~ EDIT: now JuliaLang#45993 is merged and this part isn't included. * Reverse recursion order in `call_composed`. This prevents potentially changing argument types being piped through the recursion, making inference bail out. With the reversed order, only the tuple of remaining functions is changing during recursion and is becoming strictly simpler, letting inference succeed. Co-authored-by: Shuhei Kadowaki <aviatesk@gmail.com>
Add (the equivalent of)@assume_effects :terminates_globally
tounwrap_composed
. Although it could be inferred asConst
, without the annotation, it was not elided for too complex inputs, resulting in unnecessary runtime overhead.EDIT: now effects: relax recursion detection for effects analysis #45993 is merged and this part isn't necessary.
call_composed
. This prevents potentially changing argument types being piped through the recursion, making inference bail out. With the reversed order, only the tuple of remaining functions is changing during recursion and is becoming strictly simpler, letting inference succeed.So increase in compilation time is noticeable, but execution is also much faster. (Yes, we can const-prop and completely elide
g
here). Also note that compilation time is still much better than with 1.8-rc1 (or 1.7), where it is several minutes.That said, the fact that we have to replace the concise
(c::ComposedFunction)(x...; kw...) = c.outer(c.inner(x...; kw...))
with the convoluted construction still makes me sad.Fixes #45877.