Skip to content

Dipakg custom qwen3 0825 - #5010

Draft
dipakg-lang wants to merge 4 commits into
mainfrom
dipakg-custom-qwen3-0825
Draft

Dipakg custom qwen3 0825#5010
dipakg-lang wants to merge 4 commits into
mainfrom
dipakg-custom-qwen3-0825

Conversation

@dipakg-lang

Copy link
Copy Markdown
Collaborator

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.

darisoy and others added 4 commits August 25, 2026 21:19
…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.
…aluation.

- Replaced jnp.where boolean masking with float multiplication inside the chunk rules.
- Moved sequence padding and query scaling logic before multi-head expansion to eliminate redundant FLOPs.
- Removed explicit jnp.repeat calls by leveraging implicit broadcasting via jnp.einsum.
- Fused transposes and replaced chained jnp.matmul operations with optimized jnp.einsum calls.
- Configured DenseGeneral projections to natively handle multi-dimensional shapes and replaced jnp.split with array slicing.

Performance increased on TPU v6e-256 from 2600Tokens/s/device) to ~2640 Tokens/s/device which is about 1.5% improvement.

@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 introduces support for the Qwen3-Next model architecture, including specialized Gated Delta Net (GDN) implementations and MoE configurations. It updates the Muon optimizer to support all-to-all communication and configurable Newton-Schulz steps, and refactors the NNXDecoder to support scanned blocks for Qwen3-Next. The reviewer identified several critical issues, including potential crashes due to missing platform checks in ragged gather kernels, incorrect transpose permutations in decoder blocks, key collision bugs in bias update path construction, and performance regressions in memory allocation during scanning. Additionally, the reviewer noted a potential logic error in group size distribution for ragged dot operations.

# Guard against eager initialization on non-TPU hardware (e.g. during CPU tests).
# pltpu.get_tpu_info() expects TPU hardware and will crash if executed on CPU.
if enforce_fallback or jax.devices()[0].platform != "tpu":
if enforce_fallback:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Removing the platform check or jax.devices()[0].platform != "tpu" will cause pltpu.get_tpu_info() to be executed on non-TPU platforms (such as CPU during unit tests), which will result in a crash. Please restore the platform check to safely fall back on non-TPU hardware.

Suggested change
if enforce_fallback:
if enforce_fallback or jax.devices()[0].platform != "tpu":

# Guard against eager initialization on non-TPU hardware (e.g. during CPU tests).
# pltpu.get_tpu_info() expects TPU hardware and will crash if executed on CPU.
if enforce_fallback or jax.devices()[0].platform != "tpu":
if enforce_fallback:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Removing the platform check or jax.devices()[0].platform != "tpu" will cause pltpu.get_tpu_info() to be executed on non-TPU platforms (such as CPU during unit tests), which will result in a crash. Please restore the platform check to safely fall back on non-TPU hardware.

Suggested change
if enforce_fallback:
if enforce_fallback or jax.devices()[0].platform != "tpu":

# =========================================================================
o = o_chunks.transpose(1, 0, 3, 2, 4)
o = o.reshape(B, -1, H, V_dim)
o = o_chunks.transpose(0, 1, 4, 2, 3, 5).reshape(B, seq_len, H_k * R, V_dim)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

The transpose permutation (0, 1, 4, 2, 3, 5) keeps num_chunks at axis 0 and B (batch size) at axis 1. When this is reshaped to (B, seq_len, H_k * R, V_dim), it will scramble the batch dimension because B is not the leading dimension before the reshape. To keep the batch dimension intact, the batch axis B must be transposed to axis 0 first using the permutation (1, 0, 4, 2, 3, 5).

Suggested change
o = o_chunks.transpose(0, 1, 4, 2, 3, 5).reshape(B, seq_len, H_k * R, V_dim)
o = o_chunks.transpose(1, 0, 4, 2, 3, 5).reshape(B, seq_len, H_k * R, V_dim)

Comment on lines +390 to +397
moe_bias_updates = {
"/".join(tuple(k.key for k in path if hasattr(k, "key"))): val
for path, val in jax.tree_util.tree_leaves_with_path(
intermediate_outputs
)
if tuple(k.key for k in path if hasattr(k, "key"))[-1:]
== ("moe_bias_updates",)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Using tuple(k.key for k in path if hasattr(k, "key")) to construct the path string skips all non-DictKey components, such as SequenceKey (which has idx instead of key). For sequential/non-scanned layers, this causes all layers' moe_bias_updates to map to the exact same key (e.g., "decoder/layers/moe_bias_updates"), clobbering previous layers' updates and keeping only the last one. Please include the sequence index idx in the path string to prevent key collisions.

Suggested change
moe_bias_updates = {
"/".join(tuple(k.key for k in path if hasattr(k, "key"))): val
for path, val in jax.tree_util.tree_leaves_with_path(
intermediate_outputs
)
if tuple(k.key for k in path if hasattr(k, "key"))[-1:]
== ("moe_bias_updates",)
}
moe_bias_updates = {
"/".join(
tuple(
str(k.key) if hasattr(k, "key")
else (str(k.idx) if hasattr(k, "idx") else str(k))
for k in path
)
): val
for path, val in jax.tree_util.tree_leaves_with_path(
intermediate_outputs
)
if len(path) > 0 and (
hasattr(path[-1], "key") and path[-1].key == "moe_bias_updates"
)
}

Comment on lines +333 to +338
param_paths = [
tuple(k.key for k in path if hasattr(k, "key"))
for path, _ in jax.tree_util.tree_leaves_with_path(
nnx.state(model, nnx.Param).to_pure_dict()
)
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Using tuple(k.key for k in path if hasattr(k, "key")) to construct the parameter paths skips all non-DictKey components, such as SequenceKey (which has idx instead of key). This causes a mismatch with the moe_bias_updates keys constructed in train.py for sequential/non-scanned layers, leading to a ValueError during training. Please include the sequence index idx in the path tuple to ensure correct matching.

  param_paths = [
      tuple(
          str(k.key) if hasattr(k, "key")
          else (str(k.idx) if hasattr(k, "idx") else str(k))
          for k in path
      )
      for path, _ in jax.tree_util.tree_leaves_with_path(
          nnx.state(model, nnx.Param).to_pure_dict()
      )
  ]

# 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 nnx.state(layer) directly from the scan body instead of splitting out nnx.Param will cause JAX to stack all read-only parameters along the scan dimension, leading to huge unnecessary memory allocations during the forward pass. Please restore the nnx.split logic to avoid returning and stacking read-only parameters.

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

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 the total number of tokens inputs.shape[0] is perfectly divisible by num_groups. If it is not, the sum of the group sizes in the returned RaggedDotGroupSizes will not match the total number of tokens, which can lead to correctness or runtime errors in tokamax. Consider distributing the remainder across the groups to ensure the sum matches inputs.shape[0] exactly.

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,
)

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