ctx: Any, query: torch.Tensor, key: torch.Tensor, weights: torch.Tensor,
indices: torch.Tensor, target: torch.Tensor, ratio: int, plan: CSATNDPlan, chunk_size: int,
) -> torch.Tensor:
"""Calculate native student gradients and the original scalar KL objective."""
options, metadata = _tnd_kl_metadata(plan, query.device, query.shape[1], query.shape[2], ratio)
kernel, _ = _load_kl_ops()
with torch.autocast(device_type=query.device.type, enabled=False):
dq, dk, dw, prediction = kernel(
query, key.unsqueeze(1), weights.float(), indices, target.unsqueeze(1), metadata=metadata, **options,
)
logs = []
q_start = k_start = 0
for q_length, k_length in zip(plan.q_lengths, plan.k_lengths):
q_slice = slice(q_start, q_start+q_length)
logs.append(_stable_prediction_log(
prediction[q_slice, 0].unsqueeze(0), query[q_slice].unsqueeze(0),
key[k_start:k_start+k_length].unsqueeze(0), weights[q_slice].unsqueeze(0),
indices[q_slice, 0].unsqueeze(0), chunk_size,
)[0])
q_start += q_length
k_start += k_length
log_prediction = torch.cat(logs)
loss = (target * (target.clamp_min(torch.finfo(torch.float32).tiny).log() - log_prediction)).sum()
ctx.save_for_backward(dq, dk.squeeze(1), dw)
return loss
@staticmethod
def backward(ctx: Any, seed: torch.Tensor) -> tuple:
"""Apply the upstream scalar seed to all three precomputed student gradients."""
return (*(value.float() * seed for value in ctx.saved_tensors), None, None, None, None, None)
def sparse_lightning_indexer_kl_loss(
query: torch.Tensor, key: torch.Tensor, weights: torch.Tensor, attention_query: torch.Tensor,