(
steps,
params,
exp_avgs,
exp_avg_sqs,
weight_decay=0,
beta1=0.9,
beta2=0.999,
lr=1e-3,
eps=1e-8,
)
| 96 | |
| 97 | # Our full Adam implementation |
| 98 | def foreach_map_adam( |
| 99 | steps, |
| 100 | params, |
| 101 | exp_avgs, |
| 102 | exp_avg_sqs, |
| 103 | weight_decay=0, |
| 104 | beta1=0.9, |
| 105 | beta2=0.999, |
| 106 | lr=1e-3, |
| 107 | eps=1e-8, |
| 108 | ): |
| 109 | with torch.no_grad(): |
| 110 | grads = [param.grad for param in params] |
| 111 | # update step |
| 112 | updated_steps = foreach_map(lambda x: x + 1, steps) |
| 113 | torch._foreach_copy_(steps, updated_steps) |
| 114 | |
| 115 | if weight_decay != 0: |
| 116 | foreach_map(torch.add, (grads,), alpha=weight_decay) |
| 117 | |
| 118 | # Higher-order operators (HOPs) cannot have multiple outputs at the moment |
| 119 | # need to call foreach_map once for each output |
| 120 | exp_avgs_updated = foreach_map(torch.lerp, exp_avgs, grads, 1 - beta1) |
| 121 | exp_avgs_sq_updated = foreach_map(update_exp_avg_sq, exp_avg_sqs, grads, beta2) |
| 122 | params_updated = foreach_map( |
| 123 | update_param, |
| 124 | params, |
| 125 | steps, |
| 126 | exp_avgs_updated, |
| 127 | exp_avgs_sq_updated, |
| 128 | beta1, |
| 129 | beta2, |
| 130 | lr, |
| 131 | eps, |
| 132 | ) |
| 133 | # Higher-order operators (HOPs) don't support input mutation today |
| 134 | # so manually update the states in-place |
| 135 | torch._foreach_copy_(exp_avgs, exp_avgs_updated) |
| 136 | torch._foreach_copy_(exp_avg_sqs, exp_avgs_sq_updated) |
| 137 | torch._foreach_copy_(params, params_updated) |
| 138 | return |
| 139 | |
| 140 | ##################################################################### |
| 141 | # Setting up and running the compiled kernel |
nothing calls this directly
no outgoing calls
no test coverage detected