Skip to content

Commit 99ffcf6

Browse files
committed
[NNX] Clean up transient intermediates at setup and unify metrics sowing as nnx.Intermediate
This change cleans up transient variables sowed during model creation/tracing from the persistent sharding state and checkpoint layout. 1. Clean Quantization Setup: - Updated maybe_quantize_model in quantizations.py to pop sowed nnx.Intermediate variables in-place immediately after Qwix tracing. - This cleans the initial state returned by the model factory fn, allowing us to revert the setup-time nnx.Not(nnx.Intermediate) filters in maxtext_utils.py and train_compile.py. - Optimized create_nnx_abstract_model in model_creation_utils.py to reuse abs_model.mesh and avoid calling eval_shape twice. 2. Metrics Sowing Uniformity: - Changed all self.sow("intermediates", ...) calls to self.sow(nnx.Intermediate, ...) in all pure NNX models (gemma.py, llama2.py, etc.). - Sowing string-based "intermediates" was dynamically creating custom Variable types that did not inherit from nnx.Intermediate, leading to parameter/checkpoint bloat. - train_step in train.py now strips all intermediates via nnx.Not(nnx.Intermediate) before returning. 3. Testing: - Added MaybeQuantizeModelTest in quantizations_test.py to assert that sowed intermediates are popped from the model state and that abstract model state contains no intermediates.
1 parent df07bd6 commit 99ffcf6

19 files changed

Lines changed: 114 additions & 54 deletions

src/maxtext/layers/multi_token_prediction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
# Custom Variable types for MTP intermediate outputs
3838
# These will be automatically converted to Linen mutable collections by ToLinen wrapper
3939
# The class names become collection names directly (no case conversion)
40-
class mtp_losses(nnx.Variable): # pylint: disable=invalid-name
40+
class mtp_losses(nnx.Intermediate): # pylint: disable=invalid-name
4141
"""Variable type for storing MTP loss components -> 'mtp_losses' collection."""
4242

4343

44-
class mtp_acceptance(nnx.Variable): # pylint: disable=invalid-name
44+
class mtp_acceptance(nnx.Intermediate): # pylint: disable=invalid-name
4545
"""Variable type for storing MTP acceptance predictions -> 'mtp_acceptance' collection."""
4646

4747

src/maxtext/layers/quantizations.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,10 @@ def maybe_quantize_model(model, config):
862862
dummy_segment_ids,
863863
enable_dropout=False,
864864
)
865+
# Qwix quantization runs a forward pass during tracing, which sows transient nnx.Intermediate variables
866+
# (e.g. max_logits from QK-Clip, MTP losses) into the model. Popping them here prevents structural mismatches
867+
# between the initial setup GraphDef/state_mesh_shardings and the stripped states during train steps.
868+
nnx.pop(model, nnx.Intermediate)
865869
else:
866870
model = qwix.quantize_model(model, quantization_provider)
867871
return model

src/maxtext/models/gemma.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ def __call__(
171171
)
172172

173173
if self.config.record_internal_nn_metrics:
174-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
175-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
174+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
175+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
176176
self.sow(
177-
"intermediates",
177+
nnx.Intermediate,
178178
"activation_fraction_zero",
179179
jnp.sum(layer_output == 0) / jnp.size(layer_output),
180180
)

src/maxtext/models/gemma2.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,10 @@ def __call__(
307307
layer_output = nn.with_logical_constraint(layer_output, self.activation_axis_names)
308308

309309
if self.config.record_internal_nn_metrics:
310-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
311-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
310+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
311+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
312312
self.sow(
313-
"intermediates",
313+
nnx.Intermediate,
314314
"activation_fraction_zero",
315315
jnp.sum(layer_output == 0) / jnp.size(layer_output),
316316
)

src/maxtext/models/gemma3.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,10 @@ def __call__(
242242
layer_output = nn.with_logical_constraint(layer_output, self.activation_axis_names)
243243

244244
if cfg.record_internal_nn_metrics:
245-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
246-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
245+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
246+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
247247
self.sow(
248-
"intermediates",
248+
nnx.Intermediate,
249249
"activation_fraction_zero",
250250
jnp.sum(layer_output == 0) / jnp.size(layer_output),
251251
)

src/maxtext/models/gemma4.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ def __call__(
365365
if getattr(self.config, "num_experts", 1) > 1:
366366
mlp_lnx, load_balance_loss, _ = self.mlp(attn_output, original_inputs=attention_lnx)
367367
if self.config.load_balance_loss_weight > 0.0 and load_balance_loss is not None:
368-
self.sow("intermediates", "moe_lb_loss", load_balance_loss)
368+
self.sow(nnx.Intermediate, "moe_lb_loss", load_balance_loss)
369369
else:
370370
mlp_lnx = self.mlp(attn_output, deterministic=deterministic)
371371

@@ -381,10 +381,10 @@ def __call__(
381381
layer_output = nn.with_logical_constraint(layer_output, self.activation_axis_names)
382382

383383
if cfg.record_internal_nn_metrics:
384-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
385-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
384+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
385+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
386386
self.sow(
387-
"intermediates",
387+
nnx.Intermediate,
388388
"activation_fraction_zero",
389389
jnp.sum(layer_output == 0) / jnp.size(layer_output),
390390
)

src/maxtext/models/gpt3.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,10 @@ def __call__(
510510
layer_output = nn.with_logical_constraint(layer_output, self.activation_axis_names)
511511

512512
if self.config.record_internal_nn_metrics:
513-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
514-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
513+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
514+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
515515
self.sow(
516-
"intermediates",
516+
nnx.Intermediate,
517517
"activation_fraction_zero",
518518
jnp.sum(layer_output == 0) / jnp.size(layer_output),
519519
)

src/maxtext/models/gpt_oss.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,13 @@ def __call__(
198198
)
199199

200200
if cfg.load_balance_loss_weight > 0.0 and load_balance_loss is not None:
201-
self.sow("intermediates", "moe_lb_loss", load_balance_loss)
201+
self.sow(nnx.Intermediate, "moe_lb_loss", load_balance_loss)
202202

203203
if cfg.record_internal_nn_metrics:
204-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
205-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
204+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
205+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
206206
self.sow(
207-
"intermediates",
207+
nnx.Intermediate,
208208
"activation_fraction_zero",
209209
jnp.sum(layer_output == 0) / jnp.size(layer_output),
210210
)

src/maxtext/models/llama2.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,10 @@ def __call__(
203203
layer_output = self._maybe_shard_with_logical(layer_output, self.activation_axis_names)
204204

205205
if cfg.record_internal_nn_metrics:
206-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
207-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
206+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
207+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
208208
self.sow(
209-
"intermediates",
209+
nnx.Intermediate,
210210
"activation_fraction_zero",
211211
jnp.sum(layer_output == 0) / jnp.size(layer_output),
212212
)

src/maxtext/models/llama4.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,13 +497,13 @@ def __call__(
497497
layer_output = nn.with_logical_constraint(layer_output, self.activation_axis_names)
498498

499499
if self.config.load_balance_loss_weight > 0.0 and load_balance_loss is not None:
500-
self.sow("intermediates", "moe_lb_loss", load_balance_loss)
500+
self.sow(nnx.Intermediate, "moe_lb_loss", load_balance_loss)
501501

502502
if cfg.record_internal_nn_metrics:
503-
self.sow("intermediates", "activation_mean", jnp.mean(layer_output))
504-
self.sow("intermediates", "activation_stdev", jnp.std(layer_output))
503+
self.sow(nnx.Intermediate, "activation_mean", jnp.mean(layer_output))
504+
self.sow(nnx.Intermediate, "activation_stdev", jnp.std(layer_output))
505505
self.sow(
506-
"intermediates",
506+
nnx.Intermediate,
507507
"activation_fraction_zero",
508508
jnp.sum(layer_output == 0) / jnp.size(layer_output),
509509
)

0 commit comments

Comments
 (0)