@@ -76,8 +76,8 @@ class TpRekls(opt_mixin.WeightDecayMixin, optim.Optimizer):
7676
7777 Reimplemented from scratch (not inheriting from :class:`~emerging_optimizers.soap.soap.SOAP`) so the
7878 tensor-parallel bookkeeping stays isolated. Eigenbases are not stored in optimizer state; they are
79- recomputed via :func:`~emerging_optimizers.soap.soap_utils.get_eigenbasis_svd ` from the kronecker
80- factors. Each step calls svd twice — once on the pre-update L, R for the
79+ recomputed via :func:`~emerging_optimizers.soap.soap_utils.get_eigenbasis_eigh ` from the kronecker
80+ factors. Each step calls eigh twice — once on the pre-update L, R for the
8181 :func:`~emerging_optimizers.soap.soap.update_kronecker_factors_kl_shampoo` correction, and once on
8282 the post-update L, R for the gradient projection.
8383
@@ -231,9 +231,9 @@ def step(self, closure: None = None) -> None:
231231 shampoo_beta = 1 - (1 - shampoo_beta ) / (1 - shampoo_beta ** curr_iter_1_based )
232232
233233 # KL-Shampoo correction needs the eigenbasis of the *pre-update* L, R; recompute it
234- # via svd since we do not persist eigenbases across steps.
234+ # via eigh since we do not persist eigenbases across steps.
235235 with utils .fp32_matmul_precision (self .fp32_matmul_prec ):
236- pre_eigenbasis_list = soap_utils .get_eigenbasis_svd (kronecker_factor_list )
236+ pre_eigenbasis_list = soap_utils .get_eigenbasis_eigh (kronecker_factor_list )
237237 soap .update_kronecker_factors_kl_shampoo (
238238 kronecker_factor_list ,
239239 full_grad ,
@@ -249,11 +249,15 @@ def step(self, closure: None = None) -> None:
249249 state ["R" ].copy_ (kronecker_factor_list [1 ].chunk (self .tp_size , dim = 0 )[self .tp_rank ])
250250
251251 with utils .fp32_matmul_precision (self .fp32_matmul_prec ):
252- # Rotate exp_avg from the pre-update eigenbasis to the post-update eigenbasis
253- # (matches update_eigenbasis_and_exp_avgs in soap.py for the eigh path; we use svd here).
254- state ["exp_avg" ] = soap .precondition (state ["exp_avg" ], pre_eigenbasis_list , dims = [[0 ], [1 ]])
255- eigenbasis_list = soap_utils .get_eigenbasis_svd (kronecker_factor_list )
256- state ["exp_avg" ] = soap .precondition (state ["exp_avg" ], eigenbasis_list , dims = [[0 ], [0 ]])
252+ # Rotate exp_avg from the pre-update eigenbasis to the post-update eigenbasis,
253+ # and recompute the post-update eigenbasis via eigh.
254+ eigenbasis_list , state ["exp_avg" ], state ["exp_avg_sq" ] = soap .update_eigenbasis_and_exp_avgs (
255+ kronecker_factor_list = kronecker_factor_list ,
256+ eigenbasis_list = pre_eigenbasis_list ,
257+ exp_avg_sq = state ["exp_avg_sq" ],
258+ exp_avg = state ["exp_avg" ],
259+ use_eigh = True ,
260+ )
257261
258262 full_grad_projected = soap .precondition (full_grad , eigenbasis_list , dims = [[0 ], [0 ]])
259263
0 commit comments