Skip to content

Commit 4c4fbb2

Browse files
committed
refactor tiling related functions
1 parent 57a8d52 commit 4c4fbb2

6 files changed

Lines changed: 518 additions & 353 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Functions for gradient accumulation (GA)"""
16+
17+
import jax
18+
import jax.numpy as jnp
19+
20+
21+
def gradient_accumulation_loss_and_grad(
22+
_loss_fn,
23+
config,
24+
model,
25+
params,
26+
params_shardings,
27+
data,
28+
dropout_rng,
29+
extra_dpo_args,
30+
):
31+
"""
32+
Calculates gradients using gradient accumulation.
33+
34+
This function computes the gradient of `_loss_fn` over multiple microbatches
35+
and accumulates them before returning a single, averaged gradient. It uses
36+
`jax.lax.scan` for efficient accumulation on device.
37+
38+
It also supports a `shard_optimizer_over_data` mode (e.g., ZeRO-1) where
39+
parameters are cast to bf16 and sharded *before* the accumulation loop
40+
to perform the all-gather in lower precision.
41+
42+
Args:
43+
_loss_fn: The loss function to differentiate. Its signature is expected
44+
to be: `(model, config, data, dropout_rng, params, *extra_args, is_train=True)`.
45+
config: Model and training configuration object. Must contain
46+
`gradient_accumulation_steps` and `shard_optimizer_over_data`.
47+
model: The model module.
48+
params: The model parameters (PyTree).
49+
params_shardings: The sharding constraints for the parameters (PyTree).
50+
data: A PyTree of batched data. The leading dimension is assumed
51+
to be the total batch size (microbatch_size * num_accumulations).
52+
dropout_rng: JAX PRNGKey for dropout.
53+
extra_dpo_args: A tuple of extra arguments to pass to the loss function.
54+
55+
Returns:
56+
A tuple containing:
57+
- total_loss (Array): The mean loss, averaged over all microbatches.
58+
- final_aux (PyTree): Auxiliary outputs, summed across microbatches.
59+
- raw_grads (PyTree): The accumulated and averaged gradients.
60+
"""
61+
# When using Zero-1 optimizer sharding, cast params to lower precision and apply sharding constraints
62+
# so that all-gather is done once in the lower precision before the gradient accumulation loop
63+
if config.shard_optimizer_over_data:
64+
65+
def convert_to_bf16(param):
66+
if param.dtype == jnp.float32:
67+
return param.astype(jnp.bfloat16)
68+
return param
69+
70+
ga_params = jax.tree_util.tree_map(convert_to_bf16, params)
71+
ga_params = jax.tree.map(jax.lax.with_sharding_constraint, ga_params, params_shardings)
72+
else:
73+
ga_params = params
74+
75+
grad_func = jax.value_and_grad(_loss_fn, argnums=4, has_aux=True)
76+
77+
def accumulate_gradient(acc_grad_and_loss, data):
78+
ga_params = acc_grad_and_loss["ga_params"]
79+
80+
(_, aux), cur_batch_gradient = grad_func(model, config, data, dropout_rng, ga_params, *extra_dpo_args, is_train=True)
81+
acc_grad_and_loss["loss"] += aux["total_loss"]
82+
acc_grad_and_loss["moe_lb_loss"] += aux["moe_lb_loss"]
83+
acc_grad_and_loss["mtp_loss"] += aux["mtp_loss"]
84+
acc_grad_and_loss["grad"] = jax.tree_util.tree_map(lambda x, y: x + y, cur_batch_gradient, acc_grad_and_loss["grad"])
85+
acc_grad_and_loss["total_weights"] += aux["total_weights"]
86+
return acc_grad_and_loss, aux
87+
88+
def reshape_to_microbatch_accumulations(batch_arr):
89+
"""Reshape global batch to microbatches, assuming batch axis is leading."""
90+
num_microbatches = config.gradient_accumulation_steps
91+
microbatch_shape = (batch_arr.shape[0] // num_microbatches, num_microbatches) + batch_arr.shape[1:]
92+
reshaped_batch_arr = jnp.reshape(batch_arr, microbatch_shape)
93+
return jnp.swapaxes(reshaped_batch_arr, 0, 1)
94+
95+
data = jax.tree_util.tree_map(reshape_to_microbatch_accumulations, data)
96+
init_grad = jax.tree_util.tree_map(jnp.zeros_like, ga_params)
97+
init_grad = jax.tree.map(jax.lax.with_sharding_constraint, init_grad, params_shardings)
98+
init_grad_and_loss = {
99+
"loss": 0.0,
100+
"grad": init_grad,
101+
"total_weights": 0,
102+
"moe_lb_loss": 0.0,
103+
"mtp_loss": 0.0,
104+
"ga_params": ga_params,
105+
}
106+
107+
grad_and_loss, aux = jax.lax.scan(
108+
accumulate_gradient, init_grad_and_loss, data, length=config.gradient_accumulation_steps
109+
)
110+
loss = (
111+
grad_and_loss["loss"] / grad_and_loss["total_weights"]
112+
+ grad_and_loss["moe_lb_loss"] / config.gradient_accumulation_steps
113+
+ grad_and_loss["mtp_loss"] / config.gradient_accumulation_steps
114+
)
115+
raw_grads = grad_and_loss["grad"]
116+
if config.shard_optimizer_over_data:
117+
raw_grads = jax.tree.map(jax.lax.with_sharding_constraint, raw_grads, params_shardings)
118+
raw_grads = jax.tree_util.tree_map(lambda arr: arr / grad_and_loss["total_weights"], raw_grads)
119+
aux = jax.tree.map(lambda x: jnp.sum(x, axis=0), aux) # pytype: disable=module-attr
120+
121+
return loss, aux, raw_grads

src/MaxText/max_utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,9 @@ def unbox_logicallypartioned(boxed_pytree):
500500
# https://github.com/google-research/t5x/blob/ace831eea1e2742b4299cd1a9af7e4f302038351/t5x/losses.py#L25-L101
501501
@jax.custom_vjp
502502
def cross_entropy_with_logits(
503-
logits: jnp.ndarray, targets: jnp.ndarray, z_loss: float
503+
logits: jnp.ndarray,
504+
targets: jnp.ndarray,
505+
z_loss: float = 0.0,
504506
) -> tuple[jnp.ndarray, jnp.ndarray]:
505507
"""Computes cross entropy loss with stable custom gradient.
506508
Computes a stabilized-gradient version of:

0 commit comments

Comments
 (0)