Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f814413
Support quantization for tokamax gmm v2
shuningjin Jul 15, 2026
2cec661
format
shuningjin Jul 15, 2026
b135e8e
clean test
shuningjin Jul 15, 2026
f9f37b8
fix
shuningjin Jul 16, 2026
22bd5bc
format
shuningjin Jul 17, 2026
159ea30
Merge branch 'main' of github.com:AI-Hypercomputer/maxtext into gmm2_…
shuningjin Jul 17, 2026
0db4e43
Merge branch 'main' of github.com:AI-Hypercomputer/maxtext into gmm2_…
shuningjin Jul 17, 2026
5073aef
Merge branch 'main' of github.com:AI-Hypercomputer/maxtext into gmm2_…
shuningjin Jul 20, 2026
f201c4a
Merge branch 'main' of github.com:AI-Hypercomputer/maxtext into gmm2_…
shuningjin Jul 22, 2026
a251753
refactor1
shuningjin Jul 22, 2026
f4553b6
refactor2
shuningjin Jul 22, 2026
fc5ac54
refactor3, finish major refactor
shuningjin Jul 23, 2026
fced014
refactor flag: `use_gmm_v2` as bool or tuple
shuningjin Jul 23, 2026
2ae50ca
refactor: change order
shuningjin Jul 24, 2026
61e72b2
doc: add use_gmm_v2 to moe_configuration
shuningjin Jul 24, 2026
16ac8aa
refactor: moe condition and format
shuningjin Jul 24, 2026
7b84920
Merge branch 'main' of github.com:AI-Hypercomputer/maxtext into gmm2_…
shuningjin Jul 24, 2026
51376c1
Merge branch 'main' of github.com:AI-Hypercomputer/maxtext into gmm2_…
shuningjin Jul 28, 2026
ded3f1b
refactor: gmm flag
shuningjin Jul 28, 2026
5334a53
refactor: qwix condition
shuningjin Jul 28, 2026
4d8578b
nit
shuningjin Jul 28, 2026
6225e47
quantize lhs in fwd to correct bwd
shuningjin Jul 29, 2026
201a8fc
revert quantize lhs
shuningjin Jul 30, 2026
38bd713
Merge branch 'main' of github.com:AI-Hypercomputer/maxtext into gmm2_…
shuningjin Jul 30, 2026
608305d
quantize lhs for bwd
shuningjin Jul 31, 2026
1ad5e94
refactor: pure v2 only
shuningjin Jul 31, 2026
87b2c8e
let test pass
shuningjin Jul 31, 2026
a5aac8c
let test pass
shuningjin Jul 31, 2026
9b67772
let test pass
shuningjin Jul 31, 2026
a911746
let test pass
shuningjin Jul 31, 2026
86d3272
nit
shuningjin Aug 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/guides/optimization/benchmark_and_performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ Different quantization recipes are available, including` "int8", "fp8", "fp8_ful

For v6e and earlier generation TPUs, use the "int8" recipe. For v7x and later generation TPUs, use "fp8_full". GPUs should use “fp8_gpu” for NVIDIA and "nanoo_fp8" for AMD.

See [](quantization-doc).
See [Quantization guide](../../reference/core_concepts/quantization.md).

### Choose sharding strategy

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ MaxText is an open-source, high-performance LLM framework written in Python/JAX.

- **Supported Precisions**: FP32, BF16, INT8, and FP8.
- **Ahead-of-Time Compilation (AOT)**: For faster model development/prototyping and earlier OOM detection.
- **Quantization**: Via **Qwix** (recommended) and AQT (deprecated). See the [Quantization guide](quantization-doc).
- **Quantization**: Via **Qwix** (recommended) and AQT (deprecated). See the [Quantization guide](../core_concepts/quantization.md).
- **Diagnostics**: Simple logging via `max_logging`, profiling in **XProf**, and visualization in **TensorBoard**.
- **Multi-Token Prediction (MTP)**: Enables token efficient training with multi-token prediction.
- **Elastic Training**: Fault-tolerant and dynamic scale-up/scale-down on Cloud TPUs with Pathways.
Expand Down
3 changes: 3 additions & 0 deletions src/maxtext/common/checkpointing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,9 @@ def _should_save_checkpoint_at_step(checkpoint_manager, step, config, force):
"""Returns whether MaxText should build and dispatch checkpoint args."""
if force:
return True
if step == 0 and not config.save_checkpoint_on_start:
# if step = 0, `step % config.checkpoint_period == 0` is always true, force skip
return False
if config.enable_continuous_checkpointing:
base_checkpoint_due = bool(checkpoint_manager.should_save(step))
else:
Expand Down
16 changes: 11 additions & 5 deletions src/maxtext/configs/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ load_full_state_path: ""
# async_checkpointing is true, else a synchronous one is used. If you have
# problems with the checkpointer we recommend trying the synchronous one.
enable_checkpointing: true
save_checkpoint_on_start: true
save_checkpoint_on_completion: true
async_checkpointing: true
checkpoint_period: 10_000
Expand Down Expand Up @@ -268,6 +269,16 @@ wo_tile_drhs_mlp_dim: 1024

merge_gating_gmm: false

# Use tokamax library for gmm kernel implementation
use_tokamax_gmm: false
# Whether to use GMM v2 for MoE. (Requires use_tokamax_gmm: true)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Wondering if we should simplify back to use_gmm_v2 config for users? What's the gain for using different combination?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also, could you help update this file when applies?

Licensed under the Apache License, Version 2.0 (the "License");

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the advice! I have added use_gmm_v2 to moe_configure.md.

# fwd: tokamax_v2_gmm if true, else tokamax_v1_gmm
use_gmm_v2_fwd: false
# bwd_dlhs: tokamax_v2_gmm if true, else tokamax_v1_gmm
use_gmm_v2_dlhs: false
# bwd_drhs: tokamax_v2_tgmm if true, else tokamax_v1_tgmm
use_gmm_v2_drhs: false

norm_topk_prob: false # boolean to enable the top-k probability normalization. qwen3-specific normalization of router weights.

# when moe weight matrices are sharded on both fsdp and fsdp-transpose axes, use two separate all-gather calls
Expand Down Expand Up @@ -1260,11 +1271,6 @@ use_qk_norm_in_gdn: true
# The ratio of dimension to apply ROPE on
partial_rotary_factor: 1.0

# Use tokamax library for gmm kernel implementation
use_tokamax_gmm: false
# Whether to use GMM v2 for MoE.
# Requires use_tokamax_gmm: true. Currently incompatible with quantization.
use_gmm_v2: false
use_tokamax_splash: false
# Setting this flag will use a non-pallas implementation.
use_jax_splash: false
Expand Down
3 changes: 2 additions & 1 deletion src/maxtext/configs/pyconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
from maxtext.utils import max_logging

logger = logging.getLogger(__name__)
logger.setLevel(os.environ.get("LOGLEVEL", "INFO"))
# TODO: revert before merge
# logger.setLevel(os.environ.get("LOGLEVEL", "INFO"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 The logger level restriction was commented out during development with a "revert before merge" TODO. Leaving this in the codebase can lead to verbosity issues or inconsistent logger behavior in production. Please restore the logger level setup and remove the TODO.
Suggested change
# TODO: revert before merge
# logger.setLevel(os.environ.get("LOGLEVEL", "INFO"))
logger.setLevel(os.environ.get("LOGLEVEL", "INFO"))


_BASE_CONFIG_ATTR = "base_config"
_MAX_PREFIX = "M_"
Expand Down
74 changes: 56 additions & 18 deletions src/maxtext/configs/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ class Checkpointing(BaseModel):
source_checkpoint_layout: Literal["orbax", "safetensors", "safetensors_dynamic"] = Field(
"orbax", description="The layout of the source checkpoint to load."
)
save_checkpoint_on_start: bool = Field(True, description="If True, saves an initial checkpoint upon training start.")
save_checkpoint_on_completion: bool = Field(
True, description="If True, saves a final checkpoint upon training completion."
)
Expand Down Expand Up @@ -444,7 +445,7 @@ class Quantization(BaseModel):
use_qwix_quantization: bool = Field(False, description="Whether to use qwix for quantization.")
use_manual_quantization: bool = Field(
False,
description="Whether to use manual quantization for batch split. Only used if use_batch_split_schedule is True.",
description="Whether to use manual quantization for batch split. Only used if `use_batch_split_schedule=True`.",
)
weight_quantization_calibration_method: str = Field(
"absmax",
Expand Down Expand Up @@ -616,20 +617,6 @@ class Attention(BaseModel):
use_post_attn_norm: bool = Field(False, description="Apply LayerNorm after the attention block.")
use_post_ffw_norm: bool = Field(False, description="Apply LayerNorm after the feed-forward block.")
use_ragged_attention: bool = Field(False, description="Whether to use ragged attention kernels.")
use_tokamax_gmm: bool = Field(
False,
description="Whether to use the Tokamax library for GMM kernel implementation.",
)
use_gmm_v2: bool = Field(

@CaptainO5 CaptainO5 Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we still have this config that sets all fwd, dlhs and drhs to true in types.py when true?

@shuningjin shuningjin Jul 24, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I have refactored the flag. Instead of three flags, we now use the original single flag use_gmm_v2, which is bool (e.g., use_gmm_v2=true) or tuple (e.g., use_gmm_v2=[true, false, true]).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

keep use_gmm_v2=true mode only, remove [true, false, true] for simplicity as we don't see clear benefits

False,
description=(
"Whether to use GMM v2 (with bf16 activations and weights) for MoE."
" Requires use_tokamax_gmm: true. Currently incompatible with quantization."
),
)
num_moe_emb_chunks: int = Field(
0, description="Number of chunks for overlapping token all-gather and GMM computation along embedding dimension."
)
ragged_block_size: int = Field(256, description="Block size for ragged attention.")
enable_padding_causal_mask: bool = Field(True, description="Temporary flag for Transformer Engine padding.")
use_tokamax_splash: bool = Field(False, description="Whether to use tokamax splash attention.")
Expand Down Expand Up @@ -969,6 +956,27 @@ class MoEKernels(BaseModel):

merge_gating_gmm: bool = Field(False, description="whether to merge the two gating gmm kernels into one.")

# tokamax gmm
use_tokamax_gmm: bool = Field(
False,
description="Whether to use the Tokamax library for GMM kernel implementation.",
)
use_gmm_v2_fwd: bool = Field(
False,
description="Whether to use GMM v2 for MoE forward pass. (Requires use_tokamax_gmm: true)",
)
use_gmm_v2_dlhs: bool = Field(
False,
description="Whether to use GMM v2 for MoE backward pass (dlhs). (Requires use_tokamax_gmm: true)",
)
use_gmm_v2_drhs: bool = Field(
False,
description="Whether to use GMM v2 for MoE backward pass (drhs). (Requires use_tokamax_gmm: true)",
)
num_moe_emb_chunks: int = Field(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rebase?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Previously, these are under AttentionConfig, here. I am moving them to MoEConfig.

0, description="Number of chunks for overlapping token all-gather and GMM computation along embedding dimension."
)


class DeepSeekMoE(BaseModel):
"""Configuration specific to DeepSeek-style MoE layers."""
Expand Down Expand Up @@ -2691,6 +2699,7 @@ def validate_num_moe_emb_chunks(self):
Validates that num_moe_emb_chunks is used with supported settings.
"""
if self.num_moe_emb_chunks > 0:
# TODO: update self.use_gmm_v2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: Does this need to be removed prior to merging?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I have updated the validation check for num_moe_emb_chunks + use_gmm_v2.

if not self.use_gmm_v2 or not self.use_ring_of_experts:
raise ValueError(
f"num_moe_emb_chunks > 0 requires use_gmm_v2=True and use_ring_of_experts=True. "
Expand Down Expand Up @@ -2946,6 +2955,10 @@ def get_num_target_devices():
"Please migrate to Qwix by setting use_qwix_quantization=True."
)

# Check quant config is non-empty for Qwix quantization
if self.use_qwix_quantization and not self.quantization:
raise ValueError("Qwix quantization is enabled but quantization is not set.")

# Default quantization sharding count to number of local devices if not set.
if self.quantization_local_shard_count == -1:
try:
Expand Down Expand Up @@ -3573,11 +3586,36 @@ def calculate_global_batch_sizes(per_device_batch_size, expansion_factor, num_de
if self.share_kv_projections and self.attention_type == "mla":
raise ValueError("`share_kv_projections` is not compatible with `attention_type='mla'`.")

if self.use_gmm_v2 and (self.quantization or self.use_qwix_quantization):
raise ValueError("Quantization with GMM v2 is not supported yet.")
if self.use_gmm_v2 and not self.use_tokamax_gmm:
if self.use_manual_quantization and not self.use_batch_split_schedule:
raise ValueError("manual quantization is only used when `use_batch_split_schedule=True`.")

if (self.use_gmm_v2_fwd or self.use_gmm_v2_dlhs or self.use_gmm_v2_drhs) and not self.use_tokamax_gmm:
raise ValueError("GMM v2 requires `use_tokamax_gmm=true`.")

@CaptainO5 CaptainO5 Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Shall we also add a check to disable the use of use_gmm_v2* and use_manual_quantization together?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I have added check to ensure use_manual_quantization is only applicable to batch-split.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I added another check to reflect that gmm v2 is not supported for batch-split.

# Ensure GMM v2 flags (fwd, dlhs, drhs) are set to a valid combination:
# - v1+v1+v1 (False, False, False)
# - v2+v2+v2 (True, True, True)
# - v2+v1+v2 (True, False, True)
gmm_v2_combo = (
self.use_gmm_v2_fwd,
self.use_gmm_v2_dlhs,
self.use_gmm_v2_drhs,
)
valid_combos = {
(False, False, False), # 111 (v1+v1+v1)
(True, True, True), # 222 (v2+v2+v2)
(True, False, True), # 212 (v2+v1+v2)
Comment thread
CaptainO5 marked this conversation as resolved.
Outdated
}
if gmm_v2_combo not in valid_combos:
raise ValueError(
"Invalid GMM v2 configuration combination (fwd, dlhs, drhs). "
"Allowed combinations are:\n"
" - v1+v1+v1 (False, False, False)\n"
" - v2+v2+v2 (True, True, True)\n"
" - v2+v1+v2 (True, False, True)\n"
f"But got: {gmm_v2_combo}"
)

for val in self.compress_ratios:
if val != 0 and val < 4:
raise ValueError(f"compress_ratio must be 0 (disabled) or >= 4, got {val}")
Expand Down
Loading
Loading