@@ -176,10 +176,17 @@ def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list,
176176 # In-place: mat_d_list is a fresh tensor (wrapper's `* 1.` copy on D),
177177 # so we can fuse the energy shift without the e_bcast*sd transient.
178178 mat_d_list [jj ].addcmul_ (sd [jj ], e_bcast , value = - 1 )
179+ # sd[jj] is dead after this — it's only read here in the non-uniform
180+ # kernel. Drop the wrapper-side view so the addcmul_ transient slab
181+ # can be coalesced by the caching allocator inside the loop instead
182+ # of waiting for the wrapper's `sd_b` Python name to leave scope.
183+ sd [jj ] = None
179184 for jj in range (len (mat_l_list )):
180185 mat_l_list [jj ] = mat_l_list [jj ] - e_bcast * sl [jj ]
186+ sl [jj ] = None
181187 for jj in range (len (mat_u_list )):
182188 mat_u_list [jj ] = mat_u_list [jj ] - e_bcast * su [jj ]
189+ su [jj ] = None
183190
184191 num_of_matrices = len (mat_d_list )
185192 mat_shapes = [item .shape for item in mat_d_list ] # [B, n_q, n_q]
@@ -454,6 +461,13 @@ def _to_batch(t):
454461 Sd = torch .stack (sd_b , dim = 0 ) # [K, B, n, n]
455462 Sl = torch .stack (sl_b , dim = 0 ) # [K-1, B, n, n]
456463 Su = torch .stack (su_b , dim = 0 ) # [K-1, B, n, n]
464+ # torch.stack on the wrapper's `*1.` D copies and the L/U/sd/sl/su
465+ # expanded views produces six owned 4-D tensors. The wrapper-side
466+ # lists are dead from here on — drop them now so the per-slot
467+ # `[B, n_q, n_q]` storage (≈ K × B × n² × 16 B for D) can be freed
468+ # before the kernel allocates gr_left/grl/gru.
469+ del temp_mat_d_list , temp_mat_l_list , temp_mat_u_list
470+ del sd_b , sl_b , su_b
457471 ans = recursive_gf_cal (shift_energy , L , D , U , Sd , Su , Sl ,
458472 s_in = s_in_b , s_out = s_out_b , eta = eta ,
459473 need_lesser = need_lesser ,
@@ -470,6 +484,12 @@ def _to_batch(t):
470484 need_gr_lc = need_gr_lc ,
471485 stacked = False ,
472486 keep_gr_left = keep_gr_left )
487+ # Non-uniform kernel consumed the lists by reference and nulled
488+ # individual slots as it went. Drop the wrapper-side names so the
489+ # Python list objects (and any straggler refs) are gone before
490+ # _squeeze_ans/return.
491+ temp_mat_d_list = temp_mat_l_list = temp_mat_u_list = None
492+ sd_b = sl_b = su_b = None
473493
474494 if squeezed :
475495 ans = _squeeze_ans (ans )
0 commit comments