Skip to content

Commit 744cc56

Browse files
committed
feat: directly compile step + grad function
1 parent 908e977 commit 744cc56

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

ext/LuxReactantExt/LuxReactantExt.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module LuxReactantExt
22

33
using Enzyme: Enzyme, Const, Duplicated, Active
4+
using Optimisers: Optimisers
45
using Reactant: Reactant, @compile
56
using Setfield: @set!
67
using Static: False

ext/LuxReactantExt/training.jl

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# TODO: We want to define directly on `single_train_step!` to compile the update function
2-
# as well.
31
function Lux.Training.compute_gradients_impl(
42
backend::ReactantBackend, objective_function::F,
53
data, ts::Training.TrainState) where {F}
@@ -36,3 +34,60 @@ function compute_gradients_internal(
3634
Duplicated(ps, dps), Const(st), Const(data))
3735
return dps, loss, stats, stₙ
3836
end
37+
38+
for inplace in ("!", "")
39+
fname = Symbol(:single_train_step_impl, inplace)
40+
internal_fn = Symbol(:compute_gradients_internal_and_step, inplace)
41+
42+
@eval function Lux.Training.$(fname)(backend::ReactantBackend, objective_function::F,
43+
data, ts::Training.TrainState) where {F}
44+
dps = Lux.recursive_make_zero(ts.parameters)
45+
46+
compiled_grad_and_step_function = @compile $(internal_fn)(
47+
objective_function, ts.model, data, ts.parameters, dps, ts.states,
48+
ts.optimizer_state)
49+
50+
grads, ps, loss, stats, st, opt_state = compiled_grad_and_step_function(
51+
objective_function, ts.model, data, ts.parameters, dps, ts.states,
52+
ts.optimizer_state)
53+
54+
cache = TrainingBackendCache(
55+
backend, False(), dps, (; compiled_grad_and_step_function))
56+
@set! ts.cache = cache
57+
@set! ts.objective_function = objective_function
58+
@set! ts.states = st
59+
@set! ts.parameters = ps
60+
@set! ts.optimizer_state = opt_state
61+
@set! ts.step = ts.step + 1
62+
63+
return grads, loss, stats, ts
64+
end
65+
66+
@eval function Lux.Training.$(fname)(::ReactantBackend, obj_fn::F, data,
67+
ts::Training.TrainState{<:TrainingBackendCache{ReactantBackend}, F}) where {F}
68+
dps = Lux.recursive_make_zero!!(ts.cache.dparameters)
69+
70+
grads, ps, loss, stats, st, opt_state = ts.cache.extras.compiled_grad_and_step_function(
71+
obj_fn, ts.model, data, ts.parameters, dps, ts.states, ts.optimizer_state)
72+
73+
@set! ts.states = st
74+
@set! ts.parameters = ps
75+
@set! ts.optimizer_state = opt_state
76+
@set! ts.step = ts.step + 1
77+
78+
return grads, loss, stats, ts
79+
end
80+
end
81+
82+
for inplace in ("!", "")
83+
fname = Symbol(:compute_gradients_internal_and_step, inplace)
84+
update_fn = Symbol(:update, inplace)
85+
@eval function $(fname)(objective_function::F, model, data, ps, dps,
86+
st, opt_state) where {F}
87+
_, (loss, stₙ, stats) = Enzyme.autodiff(
88+
Enzyme.ReverseWithPrimal, Const(objective_function), Active, Const(model),
89+
Duplicated(ps, dps), Const(st), Const(data))
90+
opt_state, ps = Optimisers.$(update_fn)(opt_state, ps, dps)
91+
return dps, ps, loss, stats, stₙ, opt_state
92+
end
93+
end

0 commit comments

Comments
 (0)