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

World backedge holder #2183

Merged
merged 22 commits into from
Dec 7, 2024
Merged

World backedge holder #2183

merged 22 commits into from
Dec 7, 2024

Conversation

wsmoses
Copy link
Member

@wsmoses wsmoses commented Dec 7, 2024

No description provided.

@wsmoses wsmoses requested a review from vchuravy December 7, 2024 00:10
@wsmoses
Copy link
Member Author

wsmoses commented Dec 7, 2024

@aviatesk @vchuravy @gbaraldi so the tuple backedge doesn't work. What's the right way to add a generic backedge?

@wsmoses
Copy link
Member Author

wsmoses commented Dec 7, 2024

@vchuravy this really seems to want a MI: https://github.com/JuliaLang/julia/pull/32237/files

@wsmoses
Copy link
Member Author

wsmoses commented Dec 7, 2024

@vtjnash idk if you have any thoughts here either

Copy link
Contributor

github-actions bot commented Dec 7, 2024

Benchmark Results

main d8f8a90... main/d8f8a90616dc9a...
basics/overhead 4.64 ± 0.01 ns 4.64 ± 0.01 ns 1
time_to_load 1.14 ± 0.015 s 1.13 ± 0.0014 s 1.01

Benchmark Plots

A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.
Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).

@wsmoses wsmoses merged commit 8e10a0a into main Dec 7, 2024
21 of 30 checks passed
@wsmoses wsmoses deleted the rbh branch December 7, 2024 17:05
@@ -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]
Copy link
Member

Choose a reason for hiding this comment

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

edges = Any[mi]

@vchuravy
Copy link
Member

@vchuravy this really seems to want a MI: https://github.com/JuliaLang/julia/pull/32237/files

Yeah, Jameson's comment there is correct. This should allow edges more diverse than just the mi.
as implemented correctly in the runtime https://github.com/JuliaLang/julia/blob/7192df7e900a6e4562e1670f544b8be8878ee359/src/method.c#L847-L863

Comment on lines +129 to +160
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
Copy link
Member

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.

Copy link
Member Author

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 .

Comment on lines +379 to +388
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)))
Copy link
Member

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.

Copy link
Member

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

Copy link
Member Author

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?

Comment on lines +45 to +49
@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
Copy link
Member

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.

Copy link
Member Author

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)
Copy link
Member

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.

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.

2 participants