-
Notifications
You must be signed in to change notification settings - Fork 68
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
World backedge holder #2183
World backedge holder #2183
Conversation
@vchuravy this really seems to want a MI: https://github.com/JuliaLang/julia/pull/32237/files |
@vtjnash idk if you have any thoughts here either |
Benchmark Results
Benchmark PlotsA plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR. |
@@ -5554,7 +5554,22 @@ function thunk_generator(world::UInt, source::LineNumberNode, @nospecialize(FA:: | |||
# new_ci.min_world = min_world[] | |||
new_ci.min_world = world | |||
new_ci.max_world = max_world[] | |||
new_ci.edges = Core.MethodInstance[mi] | |||
|
|||
edges = Core.MethodInstance[mi] |
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.
edges = Any[mi]
Yeah, Jameson's comment there is correct. This should allow edges more diverse than just the |
begin | ||
# Forward-rule catch all | ||
fwd_rule_be = GPUCompiler.methodinstance(typeof(rule_backedge_holder), Tuple{typeof(EnzymeRules.forward)}) | ||
# Reverse-rule catch all | ||
rev_rule_be = GPUCompiler.methodinstance(typeof(rule_backedge_holder), Tuple{typeof(EnzymeRules.augmented_primal)}) | ||
# Inactive-rule catch all | ||
ina_rule_be = GPUCompiler.methodinstance(typeof(rule_backedge_holder), Tuple{typeof(EnzymeRules.inactive)}) | ||
# All other derivative-related catch all (just for autodiff, not inference), including inactive_noinl, noalias, and inactive_type | ||
gen_rule_be = GPUCompiler.methodinstance(typeof(rule_backedge_holder), Tuple{Val{0}}) | ||
|
||
|
||
fwd_sig = Tuple{typeof(EnzymeRules.forward), <:EnzymeRules.FwdConfig, <:Enzyme.EnzymeCore.Annotation, Type{<:Enzyme.EnzymeCore.Annotation},Vararg{Enzyme.EnzymeCore.Annotation}} | ||
EnzymeRules.add_mt_backedge!(fwd_rule_be, ccall(:jl_method_table_for, Any, (Any,), fwd_sig)::Core.MethodTable, fwd_sig) | ||
|
||
rev_sig = Tuple{typeof(EnzymeRules.augmented_primal), <:EnzymeRules.RevConfig, <:Enzyme.EnzymeCore.Annotation, Type{<:Enzyme.EnzymeCore.Annotation},Vararg{Enzyme.EnzymeCore.Annotation}} | ||
EnzymeRules.add_mt_backedge!(rev_rule_be, ccall(:jl_method_table_for, Any, (Any,), rev_sig)::Core.MethodTable, rev_sig) | ||
|
||
|
||
for ina_sig in ( | ||
Tuple{typeof(EnzymeRules.inactive), Vararg{Any}}, | ||
) | ||
EnzymeRules.add_mt_backedge!(ina_rule_be, ccall(:jl_method_table_for, Any, (Any,), ina_sig)::Core.MethodTable, ina_sig) | ||
end | ||
|
||
for gen_sig in ( | ||
Tuple{typeof(EnzymeRules.inactive_noinl), Vararg{Any}}, | ||
Tuple{typeof(EnzymeRules.noalias), Vararg{Any}}, | ||
Tuple{typeof(EnzymeRules.inactive_type), Type}, | ||
) | ||
EnzymeRules.add_mt_backedge!(gen_rule_be, ccall(:jl_method_table_for, Any, (Any,), gen_sig)::Core.MethodTable, gen_sig) | ||
end | ||
end |
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.
What does this code aim to do? IIUC backedges are only triggered once and after that pruned. So this would only survive one invalidation.
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.
ah so just move this inside our interp then? Basically this does the split we discussed, since I failed to add the generic methodtable backedge earlier =/. (I genuinely tried to add it there and failed, so you're going to have to help me add a non methodinstance backedge)
so all functions get a backedge to rule_backedge_holder. And rule_backedge_holder gets a backedge from .
if interp.forward_rules | ||
Core.Compiler.add_backedge!(sv, GPUCompiler.methodinstance(typeof(Enzyme.Compiler.Interpreter.rule_backedge_holder), Tuple{typeof(EnzymeRules.forward)}, interp.world)::Core.MethodInstance) | ||
Enzyme.Compiler.Interpreter.rule_backedge_holder(Base.inferencebarrier(EnzymeRules.forward)) | ||
end | ||
if interp.reverse_rules | ||
Core.Compiler.add_backedge!(sv, GPUCompiler.methodinstance(typeof(Enzyme.Compiler.Interpreter.rule_backedge_holder), Tuple{typeof(EnzymeRules.augmented_primal)}, interp.world)::Core.MethodInstance) | ||
Enzyme.Compiler.Interpreter.rule_backedge_holder(Base.inferencebarrier(EnzymeRules.augmented_primal)) | ||
end | ||
Core.Compiler.add_backedge!(sv, GPUCompiler.methodinstance(typeof(Enzyme.Compiler.Interpreter.rule_backedge_holder), Tuple{typeof(EnzymeRules.inactive)}, interp.world)::Core.MethodInstance) | ||
Enzyme.Compiler.Interpreter.rule_backedge_holder(Base.inferencebarrier(typeof(EnzymeRules.inactive))) |
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 should have had a comment that a mi->mi
edge is cheaper than a mi->mt
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.
And generally within inference the right thing is to use something like abstract_call
. Instead of using the hacky version of GPUCompiler.methodinstance
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.
yeah sorry I don't know the absint well enough to know how to set that up, what's the right way to do?
@static if VERSION < v"1.11-" | ||
@test_broken autodiff(Forward, call_issue696, Duplicated(1.0, 1.0))[1] ≈ 0.0 | ||
else | ||
@test autodiff(Forward, call_issue696, Duplicated(1.0, 1.0))[1] ≈ 0.0 | ||
end |
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.
Yeah that tells me we are doing something wrong again.
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.
yeah...........but at least not stupid compile time , but yea.....
callinfo = NoInlineCallInfo(callinfo, atype, :inactive) | ||
else | ||
# 2. Check if rule is defined | ||
has_rule = get!(interp.rules_cache, specTypes) do | ||
if interp.forward_rules && has_frule_from_sig(interp, specTypes, sv) |
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.
Probably should have then deleted the code in tfuncs.jl
since this was the sole user.
No description provided.