Skip to content

Mhc expand - #5014

Draft
muskansh-google wants to merge 4 commits into
AI-Hypercomputer:mainfrom
muskansh-google:mhc_expand
Draft

Mhc expand#5014
muskansh-google wants to merge 4 commits into
AI-Hypercomputer:mainfrom
muskansh-google:mhc_expand

Conversation

@muskansh-google

Copy link
Copy Markdown
Contributor

Description

Start with a short description of what the PR does and how this is a change from
the past.

The rest of the description includes relevant details and context, examples:

  • why is this change being made,
  • the problem being solved and any relevant context,
  • why this is a good solution,
  • some information about the specific implementation,
  • shortcomings of the solution and possible future improvements.

If the change fixes a bug or a Github issue, please include a link, e.g.,:
FIXES: b/123456
FIXES: #123456

You can also provide a comma-separated list. If you don't want to close a bug but
simply to reference it, use BUGS, e.g.:
BUGS: b/123456

Notice 1: Once all tests pass, the "pull ready" label will automatically be assigned.
This label is used for administrative purposes. Please do not add it manually.

Notice 2: For external contributions, our settings currently require an approval from a MaxText maintainer to trigger CI tests.

Tests

Please describe how you tested this change, and include any instructions and/or
commands to reproduce.

Checklist

Before submitting this PR, please make sure (put X in square brackets):

  • I have performed a self-review of my code. For an optional AI review, add the gemini-review label.
  • I have necessary comments in my code, particularly in hard-to-understand areas.
  • I have run end-to-end tests tests and provided workload links above if applicable.
  • I have made or will make corresponding changes to the doc if needed, including adding new documentation pages to the relevant Table of Contents (toctree directive) as explained in our documentation.

…uon sharding, and mHC-lite Pallas/Mosaic kernels on TPU v6e-256.

- Integrate DeepSeek mHC-lite architecture and high-performance Mosaic/Pallas TPU kernels with custom VJP rules and SPMD shard_map integration.
- Support Qwen3-Next 80B architecture with Gated Delta Net (GDNv3) and Pallas custom VJP in hybrid_gdn.py.
- Configure Muon optimizer and sharding rules for MoE parameters (shard-exp-on-fsdp).
- Update AOT compile, XManager Borg, and XPK launch scripts for Qwen3-Next 80B on TPU v6e-256 (glp_16x16) topology to enable mHC-lite and Pallas kernel flags.
- Add and update unit tests for mHC, GDN, Muon utilities, NNX decoders, and parameter mapping.
- Validated clean AOT compilation on TPU v6e-256 via qn80b-v6e256-compile.sh and unit tests via mhc_test.
- Integrates sharding-aware Muon optimizer supporting Newton-Schulz iterations and partition padding into MaxText.
- Fixes weight dimension indexing in muon_utils.py to account for layer scanning, 1D tensor exclusions, and rank-aware 2D attention projection handling.
- Fixes routing gate exclusion logic to use exact segment matching across gate and router variants.
- Plumbs NamedSharding in sharding.py by collecting momentum trees across multi-branch partitioned optimizers, extracting MuonState NamedTuples, and filtering optax.MaskedNode placeholders.
- Threads mesh through train_utils.py, train_compile.py, and maxtext_engine.py to get_optimizer.
- Add some minor tests throughout.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for Qwen3-Next models, including new configurations, scannable blocks, and a hybrid Gated Delta Net (GDN) implementation. It also integrates Manifold-Constrained Hyper Connections (mHC) and updates the Muon optimizer dimension mapping to be invariant to layer scanning. Critical feedback identifies several issues: an AttributeError in parameter mapping, a memory regression (OOM risk) in nnx_decoders.py from returning the full nnx.state inside a scan, a dangerous bare except: pass block, potential shape mismatches in Tokamax group sizes when inputs are not perfectly divisible, and a crash on non-TPU platforms due to the removal of a platform check in ragged_gather.py.

Comment on lines +1919 to +1925
for i in range(config.base_num_decoder_layers):
prefix = f"params-decoder-layers_{i}"
block_idx = i % config.inhomogeneous_layer_cycle_interval
is_full_attention_layer = (
block_idx + 1
) % config.inhomogeneous_layer_cycle_interval == 0
_attach_block_hooks(prefix, is_global=is_full_attention_layer)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using config.base_num_decoder_layers and config.inhomogeneous_layer_cycle_interval will raise an AttributeError because config is the HuggingFace configuration dictionary (or object), which does not contain these MaxText-specific fields. Instead, you should use the local variables num_main_layers and layer_cycle_interval which are already defined in the outer scope.

Suggested change
for i in range(config.base_num_decoder_layers):
prefix = f"params-decoder-layers_{i}"
block_idx = i % config.inhomogeneous_layer_cycle_interval
is_full_attention_layer = (
block_idx + 1
) % config.inhomogeneous_layer_cycle_interval == 0
_attach_block_hooks(prefix, is_global=is_full_attention_layer)
for i in range(num_main_layers):
prefix = f'params-decoder-layers_{i}'
block_idx = i % layer_cycle_interval
is_full_attention_layer = (
block_idx + 1
) % layer_cycle_interval == 0
_attach_block_hooks(prefix, is_global=is_full_attention_layer)

# This prevents huge unnecessary memory allocation.
_, _, updated_state = nnx.split(layer, nnx.Param, ...)
return new_carry, updated_state
return new_carry, nnx.state(layer)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Returning the full nnx.state(layer) (which includes read-only nnx.Param variables) inside the scan body will cause JAX to stack all parameters along the scan dimension. This re-introduces the huge unnecessary memory allocation that the original code explicitly avoided to prevent Out-Of-Memory (OOM) issues during compilation and execution. Please revert to splitting the state and returning only the updated non-parameter state.

Suggested change
return new_carry, nnx.state(layer)
_, _, updated_state = nnx.split(layer, nnx.Param, ...)
return new_carry, updated_state

Comment on lines +933 to +936
try:
forked_rngs = rngs.fork(split=length)
except: # pylint: disable=bare-except
pass

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The bare except: pass block is highly dangerous here. If rngs.fork raises an exception, forked_rngs will remain undefined, which will immediately cause a NameError or UnboundLocalError on the next line when nnx.split(forked_rngs) is called. Since rngs is a required argument and must be valid, this try-except block should be removed.

    forked_rngs = rngs.fork(split=length)

Comment thread src/maxtext/layers/moe.py
Comment on lines +1517 to 1522
num_groups = group_sizes.shape[0]
avg_size = inputs.shape[0] // num_groups
return tokamax.RaggedDotGroupSizes(
group_sizes,
inputs.shape[0],
(avg_size,) * num_groups,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using (avg_size,) * num_groups assumes that inputs.shape[0] is perfectly divisible by num_groups. If there is a remainder, the sum of the group sizes will be less than the total number of inputs, which can cause shape mismatch or out-of-bounds errors in Tokamax. Please distribute the remainder evenly across the groups.

Suggested change
num_groups = group_sizes.shape[0]
avg_size = inputs.shape[0] // num_groups
return tokamax.RaggedDotGroupSizes(
group_sizes,
inputs.shape[0],
(avg_size,) * num_groups,
)
num_groups = group_sizes.shape[0]
avg_size = inputs.shape[0] // num_groups
remainder = inputs.shape[0] % num_groups
sizes = tuple(avg_size + (1 if i < remainder else 0) for i in range(num_groups))
return tokamax.RaggedDotGroupSizes(
group_sizes,
sizes,
)

Comment on lines +413 to 414
if enforce_fallback:
return _fallback_implementation(x, indices, weights, has_weights)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Removing the TPU platform check or jax.devices()[0].platform != "tpu" means that running this function on non-TPU platforms (such as CPU during unit tests or local development) will attempt to call pltpu.get_tpu_info(), which will crash. Please restore the platform check to safely guard against non-TPU execution.

Suggested change
if enforce_fallback:
return _fallback_implementation(x, indices, weights, has_weights)
if enforce_fallback or jax.devices()[0].platform != 'tpu':
return _fallback_implementation(x, indices, weights, has_weights)

@muskansh-google
muskansh-google force-pushed the mhc_expand branch 5 times, most recently from bd34611 to 5db6100 Compare August 26, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants