Skip to content

Add 8 priority human optimized kernels and SWA into JaxBench level 2 - #101

Open
shangkunwang01 wants to merge 8 commits into
mainfrom
shangkun-jaxbench-level2
Open

shangkunwang01 wants to merge 8 commits into
mainfrom
shangkun-jaxbench-level2

Conversation

@shangkunwang01

@shangkunwang01 shangkunwang01 commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator
  1. Prepare 8 priority human optimized kernels and SWA into JaxBench level 2
  2. Create a verification file in for adapted dataset MaxKernel/evaluation/jaxbench_adapted_dataset/verify_with_jaxbench.py
  3. Verify the added adpated code matches JaxBench code
Verifying 11p_Megablox_GMM...
  [PASS] 11p_Megablox_GMM
Verifying 1p_Flash_Attention...
  [PASS] 1p_Flash_Attention
Verifying 2p_GQA_Attention...
  [PASS] 2p_GQA_Attention
Verifying 3p_MLA_Attention...
  [PASS] 3p_MLA_Attention
Verifying 4p_Sparse_Attention...
  [PASS] 4p_Sparse_Attention
Verifying 51p_DeepSeek_V4_CSA...
  [PASS] 51p_DeepSeek_V4_CSA[0]
  [PASS] 51p_DeepSeek_V4_CSA[1]
  [PASS] 51p_DeepSeek_V4_CSA[2]
  [PASS] 51p_DeepSeek_V4_CSA[3]
  [PASS] 51p_DeepSeek_V4_CSA[4]
  [PASS] 51p_DeepSeek_V4_CSA[5]
  [PASS] 51p_DeepSeek_V4_CSA[6]
  [PASS] 51p_DeepSeek_V4_CSA[7]
  [PASS] 51p_DeepSeek_V4_CSA[8]
  [PASS] 51p_DeepSeek_V4_CSA[9]
Verifying 52p_DeepSeek_V4_HCA...
  [PASS] 52p_DeepSeek_V4_HCA[0]
  [PASS] 52p_DeepSeek_V4_HCA[1]
  [PASS] 52p_DeepSeek_V4_HCA[2]
  [PASS] 52p_DeepSeek_V4_HCA[3]
  [PASS] 52p_DeepSeek_V4_HCA[4]
  [PASS] 52p_DeepSeek_V4_HCA[5]
  [PASS] 52p_DeepSeek_V4_HCA[6]
  [PASS] 52p_DeepSeek_V4_HCA[7]
  [PASS] 52p_DeepSeek_V4_HCA[8]
  [PASS] 52p_DeepSeek_V4_HCA[9]
Verifying 53p_DeepSeek_V4_SWA...
  [PASS] 53p_DeepSeek_V4_SWA[0]
  [PASS] 53p_DeepSeek_V4_SWA[1]
  [PASS] 53p_DeepSeek_V4_SWA[2]
  [PASS] 53p_DeepSeek_V4_SWA[3]
  [PASS] 53p_DeepSeek_V4_SWA[4]
  [PASS] 53p_DeepSeek_V4_SWA[5]
  [PASS] 53p_DeepSeek_V4_SWA[6]
  [PASS] 53p_DeepSeek_V4_SWA[7]
Verifying 6p_Paged_Attention...
  [PASS] 6p_Paged_Attention
Verifying 7p_Ragged_Paged_Attention...
  [PASS] 7p_Ragged_Paged_Attention
Verifying 8p_GEMM...
  [PASS] 8p_GEMM

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

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.

Code Review

This pull request introduces several new JAXBench workloads, including implementations for Megablox GMM, Flash Attention, GQA Attention, and MLA Attention. The review feedback highlights a critical issue regarding the order of operations for attention bias and scaling in the Flash Attention kernel, which affects numerical correctness. Other feedback points out opportunities for code cleanup, such as improving type hints, refactoring logic for clarity, and fixing import placement to follow PEP 8 guidelines.

Comment on lines +401 to +408
if ab_tile_ref is not None:
ab = ab_tile_ref[
(*batch_idx, pl.dslice(None), pl.dslice(start_k, block_k))
].astype(jnp.float32)
s += ab

if sm_scale != 1.0:
s *= sm_scale

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.

high

The order of applying attention bias and sm_scale seems incorrect. Currently, the bias is added before scaling: (Q @ K.T + bias) * sm_scale. The standard implementation of attention applies the scale factor before adding the bias: (Q @ K.T * sm_scale) + bias. This should be changed to ensure correctness, especially if the model was trained with the standard attention implementation. This issue appears in multiple places in this file (including the reference implementation and backward pass) and should be fixed consistently.

Suggested change
if ab_tile_ref is not None:
ab = ab_tile_ref[
(*batch_idx, pl.dslice(None), pl.dslice(start_k, block_k))
].astype(jnp.float32)
s += ab
if sm_scale != 1.0:
s *= sm_scale
if sm_scale != 1.0:
s *= sm_scale
# Add attention bias if needed.
# TODO(tanburn) Should the attention bias be added before or after
# multiplication by sm_scale?
if ab_tile_ref is not None:
ab = ab_tile_ref[
(*batch_idx, pl.dslice(None), pl.dslice(start_k, block_k))
].astype(jnp.float32)
s += ab

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.

No fix. Keep consistent with the original implementation.

Comment on lines +401 to +408
repeats, rem = divmod(block_k, NUM_LANES)
if rem:
raise NotImplementedError(
f"kv block size must be a multiple of {NUM_LANES}"
)
q_segment_ids = jnp.tile(
q_segment_ids_tile_ref[batch_idx[0]], (1, repeats)
)

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.

high

The order of applying attention bias and sm_scale seems incorrect. Currently, the bias is added before scaling: (Q @ K.T + bias) * sm_scale. The standard implementation of attention applies the scale factor before adding the bias: (Q @ K.T * sm_scale) + bias. This should be changed to ensure correctness, especially if the model was trained with the standard attention implementation. This issue appears in multiple places in this file and should be fixed consistently.

      if sm_scale != 1.0:
        s *= sm_scale

      # Add attention bias if needed.
      # TODO(tanburn) Should the attention bias be added before or after
      # multiplication by sm_scale?
      if ab_tile_ref is not None:
        ab = ab_tile_ref[
            (*batch_idx, pl.dslice(None), pl.dslice(start_k, block_k))
        ].astype(jnp.float32)
        s += ab

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.

Same as above.

return tiles, rem


GroupMetadata = Any # TODO(enriqueps): Clean this up and use a namedtuple

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.

medium

The type hint for GroupMetadata is Any, with a TODO to use a NamedTuple. Using a NamedTuple would improve readability and make the code easier to understand and maintain, clarifying what the tuple returned by make_group_metadata contains.

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.

Same as above.

Comment on lines +218 to +220
partial_tile_mask = jnp.logical_or(
(group_offsets[:-1] % tm) == 0, group_sizes == 0
)

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.

medium

As the TODO on line 217 suggests, the naming and logic for partial_tile_mask could be clearer. This mask identifies groups that do not have a partial tile at their start. Renaming it could improve readability. For example, a name like is_aligned_or_empty_mask would more directly convey its purpose.

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.

Same as above.

Comment on lines +251 to +252
group_ids = jnp.roll(group_ids, shift=-first_tile_in_shard, axis=0)
m_tile_ids = jnp.roll(m_tile_ids, shift=-first_tile_in_shard, axis=0)

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.

medium

As the TODO on line 249 suggests, using jnp.roll here can be inefficient as it may involve unnecessary data movement on the accelerator. This logic could be moved inside the Pallas kernel by passing first_tile_in_shard as an argument and adjusting the indices within the kernel. This would avoid the overhead of jnp.roll.

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.

Same as above.

Comment on lines +852 to +864
import time
inputs = create_inputs()
fn = jax.jit(workload)
for _ in range(num_warmup):
out = fn(*inputs)
out.block_until_ready()
times = []
for _ in range(num_iters):
t0 = time.perf_counter()
out = fn(*inputs)
out.block_until_ready()
times.append(time.perf_counter() - t0)
import numpy as np

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.

medium

Imports should be at the top of the file, as per PEP 8 guidelines. import time and import numpy as np should be moved from inside the benchmark function to the top-level of the module. This improves code organization and avoids re-importing modules. This issue is present in most of the new baseline.py files in this pull request.

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.

Updated.

new_kv_c: jax.Array, # [max_num_tokens, actual_lkv_dim]
new_k_pe: jax.Array, # [max_num_tokens, actual_r_dim]
cache_kv: jax.
Array, # [total_num_pages, page_size_per_kv_packing, kv_packing, lkv_dim]

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.

medium

The type hint comment for cache_kv has a typo. The last dimension should be the combined and aligned key-value dimension, lkv_dim + r_dim, not just lkv_dim.

Suggested change
Array, # [total_num_pages, page_size_per_kv_packing, kv_packing, lkv_dim]
Array, # [total_num_pages, page_size_per_kv_packing, kv_packing, align_to(lkv_dim + r_dim, 128)]

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 it as it is to be consistent with the original code.

@NinaCai NinaCai left a comment

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.

Could you rename swa as 53p_DeepSeek_V4_MLA_SWA in both JaxBench and jaxbench_adapted_dataset?

If you plan to work on CSA and HCA as well. Could you follow 51p_DeepSeek_V4_CSA and 52p_DeepSeek_V4_HCA?

@shangkunwang01
shangkunwang01 force-pushed the shangkun-jaxbench-level2 branch from ebf6a45 to 8f170d3 Compare September 10, 2026 00:00
@shangkunwang01

Copy link
Copy Markdown
Collaborator Author

Could you rename swa as 53p_DeepSeek_V4_MLA_SWA in both JaxBench and jaxbench_adapted_dataset?

If you plan to work on CSA and HCA as well. Could you follow 51p_DeepSeek_V4_CSA and 52p_DeepSeek_V4_HCA?

Updated.

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.

3 participants